System.Text.Json 역 직렬화가 JsonException "많이 읽거나 충분하지 않음"으로 실패합니다.

GKalnytskyi

이 질문 System.Text.Json은 .Net Core 3.1의 사용자 지정 역 직렬화 클래스에 적용됩니다 .

사용자 지정 역 직렬화 클래스가 이미 필요한 데이터를 생성 했음에도 불구하고 JSON 스트림의 끝까지 읽어야하는 이유를 이해하려고합니다. 그렇지 않으면 역 직렬화가 JsonException"너무 많이 읽거나 충분하지 않음"으로 끝나고 실패합니다 .

System.Text.Json([ 1 ], [ 2 ])에 대한 Microsoft 문서를 읽었 지만 알아낼 수 없었습니다.

다음은 문서의 예입니다.

{
    "Response": {
        "Result": [
            {
                "Code": "CLF",
                "Id": 49,
                "Type": "H"
            },
            {
                "Code": "CLF",
                "Id": 42,
                "Type": "C"
            }
        ]
    }
}

DTO 클래스 및 역 직렬화 방법은 다음과 같이 정의됩니다.

public class EntityDto
{
    public string Code { get; set; }
    public int Id { get; set; }
    public string Type { get; set; } 
}

// This method is a part of class EntityDtoIEnumerableConverter : JsonConverter<IEnumerable<EntityDto>>
public override IEnumerable<EntityDto> Read(
    ref Utf8JsonReader reader,
    Type typeToConvert,
    JsonSerializerOptions options)
{
    if (reader.TokenType != JsonTokenType.StartObject)
    {
        throw new JsonException("JSON payload expected to start with StartObject token.");
    }

    while ((reader.TokenType != JsonTokenType.StartArray) && reader.Read()) { }

    var eodPostions = JsonSerializer.Deserialize<EntityDto[]>(ref reader, options);

    // This loop is required to not get JsonException
    while (reader.Read()) { }

    return new List<EntityDto>(eodPostions);
}

deserialization 클래스가 호출되는 방법은 다음과 같습니다.

var serializerOptions = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true
};
serializerOptions.Converters.Add(new EntityDtoIEnumerableConverter());

HttpResponseMessage message = await httpClient.GetAsync(requestUrl);
message.EnsureSuccessStatusCode();

var contentStream = await msg.Content.ReadAsStreamAsync();
var result = await JsonSerializer.DeserializeAsync<IEnumerable<EntityDto>>(contentStream, serializerOptions);

while (reader.Read()) { }deserialization 메서드 의 마지막 루프 가 없거나 주석 처리 된 경우 마지막 호출 await JsonSerializer.DeserializeAsync<...은으로 JsonException끝나는으로 실패합니다 read too much or not enough. 아무도 이유를 설명 할 수 있습니까? 아니면이 역 직렬화를 작성하는 더 좋은 방법이 있습니까?

.NET을 사용 하도록 두 번째 코드 블록을 업데이트 했습니다 EntityDtoIEnumerableConverter.

dbc

개체를 읽을 때 원래 위치했던 개체토큰 에있는 위치를 JsonConverter<T>.Read()그대로 두어야합니다 . (그리고 배열 의 경우 원본 배열의) 여러 수준의 JSON을 구문 분석 하는 메서드를 작성할 때 입력시 판독기의 를 기억 한 다음 동일한 깊이에서를 찾을 때까지 읽음으로써 이를 수행 할 수 있습니다 .Utf8JsonReaderEndObjectEndArrayRead()CurrentDepthEndObject

당신 때문에 EntityDtoIEnumerableConverter.Read()방법은 그것이로 배열을 직렬화 복원하는에 배열이 발생 될 때까지 JSON 토큰 계층을 내려 노력 것으로 보인다 EntityDto[](본질적으로 박리 "Response""Result"래퍼 속성) 다음과 같이 코드를 다시 작성할 수 있습니다 :

public override IEnumerable<EntityDto> Read(
    ref Utf8JsonReader reader,
    Type typeToConvert,
    JsonSerializerOptions options)
{
    if (reader.TokenType != JsonTokenType.StartObject)
    {
        throw new JsonException("JSON payload expected to start with StartObject token.");
    }

    List<EntityDto> list = null;    
    var startDepth = reader.CurrentDepth;

    while (reader.Read())
    {
        if (reader.TokenType == JsonTokenType.EndObject && reader.CurrentDepth == startDepth)
            return list;
        if (reader.TokenType == JsonTokenType.StartArray)
        {
            if (list != null)
                throw new JsonException("Multiple lists encountered.");
            var eodPostions = JsonSerializer.Deserialize<EntityDto[]>(ref reader, options);
            (list = new List<EntityDto>(eodPostions.Length)).AddRange(eodPostions);
        }
    }
    throw new JsonException(); // Truncated file or internal error
}

메모:

  • 원래 코드에서 배열이 역 직렬화 되 자마자 반환했습니다. 이후 JsonSerializer.Deserialize<EntityDto[]>(ref reader, options)에만이 중첩 된 배열의 마지막에 독자를 진행하면 필요한 객체 끝까지 독자를 진행하지 않습니다. 이로 인해 발생한 예외가 발생했습니다. (JSON 스트림이 끝날 때까지 진행하는 것은 현재 객체가 루트 객체때도 작동 한 것처럼 보이지만 중첩 된 객체에서는 작동하지 않았을 것입니다.)

  • 링크 된 .NET에서 JSON 직렬화 (마샬링) 용 사용자 지정 변환기를 작성하는 방법 에 대한 설명서 문서에 현재 표시된 변환기가 없습니다. 수행하는 동안 여러 수준의 JSON을 단일 .Net 개체로 병합하려고 시도하므로 현재 깊이를 추적하는 것은 실제로 발생하지 않은 것 같습니다.

여기에 데모 바이올린 .

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

System.Text.Json : 자동 캐스팅으로 JSON 역 직렬화

분류에서Dev

json 문자열에없는 enum 속성이있는 모델로 역 직렬화 할 때 System.Text.Json이 강제로 실패합니다.

분류에서Dev

System.Text.Json 사용자 지정 직렬화 / 역 직렬화

분류에서Dev

System.Text.JSON은 Newtonsoft가 수행하는 작업을 역 직렬화하지 않습니다.

분류에서Dev

ServiceStack.Text json serializer는 대괄호가있는 원시 문자열을 jsv로 역 직렬화합니다.

분류에서Dev

처음으로 NewtonSoft (JsonConvert.DeserializeObject <> ()를 사용하여 JSON 대 System.Text.Json (JsonSerializer.Deserialize <> () 역 직렬화)

분류에서Dev

System.Text.Json-중첩 된 개체를 문자열로 역 직렬화

분류에서Dev

System.Text.Json을 사용하여 IConfiguration을 다시 Json으로 직렬화

분류에서Dev

System.Text.Json : System.IO.Pipelines에서 역 직렬화

분류에서Dev

System.Text.Json을 사용하여 목록을 비동기 적으로 역 직렬화

분류에서Dev

System.Text.Json을 사용하여 과학적 표기법을 long으로 역 직렬화

분류에서Dev

JSON 개체를 System.Guid 형식으로 역 직렬화

분류에서Dev

.NET Core 3.1에서 System.Text.Json을 사용한 역 직렬화로 인해 null 속성 값이 발생합니다.

분류에서Dev

System.Text.Json 개체 배열 역 직렬화

분류에서Dev

System.Text.Json에서 NodaTime Instant 역 직렬화

분류에서Dev

현재 JSON 개체 (예 : { "name": "value"})를 'System.Collections.Generic.List 유형으로 역 직렬화 할 수 없습니다.

분류에서Dev

System.Text.Json을 사용하여 동적 속성을 포함하는 클래스로 JSON 역 직렬화

분류에서Dev

Json.Net 역 직렬화로 인해 null 개체가 발생합니다.

분류에서Dev

JSon을 C #으로 역 직렬화 할 수 없습니다.

분류에서Dev

System.Text.Json.JsonException : JSON 값을 변환 할 수 없습니다.

분류에서Dev

json.net으로 JSON 역 직렬화

분류에서Dev

System.Text.Json API를 사용하여 스트림을 개체로 역 직렬화하는 방법

분류에서Dev

C # System.Text.Json "반올림"은 직렬화 중에 두 배가됩니다.

분류에서Dev

System.Text.Json을 사용하여 JSON으로 직렬화하는 동안 개체에 루트 요소 추가

분류에서Dev

다단계 중첩으로 JSON 역 직렬화

분류에서Dev

Rust로 가능한 여러 값으로 JSON 역 직렬화

분류에서Dev

System.Json의 모델로 JsonValue 역 직렬화

분류에서Dev

역 직렬화 할 때 ServiceStack JsonServiceClient가 자동으로 실패 함

분류에서Dev

JSON을 C #의 Dictionary <string, List <string >>으로 역 직렬화하려고합니다.

Related 관련 기사

  1. 1

    System.Text.Json : 자동 캐스팅으로 JSON 역 직렬화

  2. 2

    json 문자열에없는 enum 속성이있는 모델로 역 직렬화 할 때 System.Text.Json이 강제로 실패합니다.

  3. 3

    System.Text.Json 사용자 지정 직렬화 / 역 직렬화

  4. 4

    System.Text.JSON은 Newtonsoft가 수행하는 작업을 역 직렬화하지 않습니다.

  5. 5

    ServiceStack.Text json serializer는 대괄호가있는 원시 문자열을 jsv로 역 직렬화합니다.

  6. 6

    처음으로 NewtonSoft (JsonConvert.DeserializeObject <> ()를 사용하여 JSON 대 System.Text.Json (JsonSerializer.Deserialize <> () 역 직렬화)

  7. 7

    System.Text.Json-중첩 된 개체를 문자열로 역 직렬화

  8. 8

    System.Text.Json을 사용하여 IConfiguration을 다시 Json으로 직렬화

  9. 9

    System.Text.Json : System.IO.Pipelines에서 역 직렬화

  10. 10

    System.Text.Json을 사용하여 목록을 비동기 적으로 역 직렬화

  11. 11

    System.Text.Json을 사용하여 과학적 표기법을 long으로 역 직렬화

  12. 12

    JSON 개체를 System.Guid 형식으로 역 직렬화

  13. 13

    .NET Core 3.1에서 System.Text.Json을 사용한 역 직렬화로 인해 null 속성 값이 발생합니다.

  14. 14

    System.Text.Json 개체 배열 역 직렬화

  15. 15

    System.Text.Json에서 NodaTime Instant 역 직렬화

  16. 16

    현재 JSON 개체 (예 : { "name": "value"})를 'System.Collections.Generic.List 유형으로 역 직렬화 할 수 없습니다.

  17. 17

    System.Text.Json을 사용하여 동적 속성을 포함하는 클래스로 JSON 역 직렬화

  18. 18

    Json.Net 역 직렬화로 인해 null 개체가 발생합니다.

  19. 19

    JSon을 C #으로 역 직렬화 할 수 없습니다.

  20. 20

    System.Text.Json.JsonException : JSON 값을 변환 할 수 없습니다.

  21. 21

    json.net으로 JSON 역 직렬화

  22. 22

    System.Text.Json API를 사용하여 스트림을 개체로 역 직렬화하는 방법

  23. 23

    C # System.Text.Json "반올림"은 직렬화 중에 두 배가됩니다.

  24. 24

    System.Text.Json을 사용하여 JSON으로 직렬화하는 동안 개체에 루트 요소 추가

  25. 25

    다단계 중첩으로 JSON 역 직렬화

  26. 26

    Rust로 가능한 여러 값으로 JSON 역 직렬화

  27. 27

    System.Json의 모델로 JsonValue 역 직렬화

  28. 28

    역 직렬화 할 때 ServiceStack JsonServiceClient가 자동으로 실패 함

  29. 29

    JSON을 C #의 Dictionary <string, List <string >>으로 역 직렬화하려고합니다.

뜨겁다태그

보관