Десериализовать ошибку JSON при преобразовании значения в определенный тип - PullRequest
0 голосов
/ 02 сентября 2018

У меня есть бэкэнд-модель Django с REST Services, которая создает JSON. JSON, который я получаю (частично), выглядит следующим образом:

[
  {
    "id": 1,
    "username": "T1",
    "tel": "",
    "created_on": "2018-09-03T16:29:20.903315Z",
    "last_login": null,
    "hasContacts": [

    ],
    "myChanges": [

    ],
    "helpsOnChanges": [

    ],
    "shouldHelpOnChanges": [
      1
    ],
    "welldone_set": [
      {
        "id": 1,
        "created_on": "2018-09-03T16:29:20.925327Z",
        "comment": "You rock1",
        "change": 1,
        "helper": 1
      }
    ]
  },
  {
    "id": 2,
    "username": "T2",
    "tel": "",
    "created_on": "2018-09-03T16:29:20.903315Z",
    "last_login": null,
    "hasContacts": [

    ],
    "myChanges": [
      {
        "id": 1,
        "name": "Stop smoking",
        "created_on": "2018-09-03T16:29:20.923315Z",
        "change": "I want to stop smoking",
        "finished_on": null,
        "success": false,
        "helpee": 2,
        "helper": [

        ],
        "requestedHelpers": [
          1
        ],
        "welldone_set": [
          {
            "id": 1,
            "created_on": "2018-09-03T16:29:20.925327Z",
            "comment": "You rock1",
            "change": 1,
            "helper": 1
          }
        ]
      }
    ],
    "helpsOnChanges": [

    ],
    "shouldHelpOnChanges": [

    ],
    "welldone_set": [

    ]
  }
]

Явная ошибка вызова JSONConvert.Deserialize теперь:

2018-09-02T18: 57: 13.145 Ошибка Ошибка десериализации App.ViewModels.Change. Ошибка преобразования значения 1 в тип «App.ViewModels.User». Путь '[0] .myChanges [0] .helpee', строка 1, позиция 275.

Это относится к атрибуту "helpee", который имеет тип user. Инфраструктура Django только помещает идентификатор пользователя в этот список, что имеет смысл, поскольку пользователь уже был передан в этом JSON до приведенного выше результата.

Так почему же Newtonsoft.JSON не может решить эту проблему? Может ли он связать этот идентификатор с фактическим экземпляром пользователя с тем же идентификатором?

Заранее спасибо! Wolf

Редактировать: Для уточнения сериализатор моего Django Backend:

    class ChangeSerializer(serializers.ModelSerializer):
        welldone_set = WellDoneSerializer(many=True)
        class Meta:
            model = Change
            fields = ('id',
                      'name', 
                      'created_on', 
                      'change', 
                      'finished_on', 
                      'success', 
                      'helpee', 
                      'helper', 
                      'requestedHelpers', 
                      'welldone_set') 
ChangeSerializer.helpee = UserSerializer();
ChangeSerializer.helper = UserSerializer(many=True);
ChangeSerializer.requestedHelpers = UserSerializer(many=True);

Как видите, helpee на самом деле является объектом, а не просто идентификатором

Редактировать 2: Обновлен JSON для завершения

Редактировать 3: Мой метод десериализации. Исключение выдается в строке десериализатора.

public static async Task<List<T>> getDataListFromService<T>(string queryString)
        {
            Debug.WriteLine("###Building HttpClient for " + queryString);
            HttpClient client = new HttpClient();
            Debug.WriteLine("###Building GetAsync...");
            HttpResponseMessage response = await client.GetAsync(queryString);
            Debug.WriteLine("### HTTP Get Response: " + response.ReasonPhrase);
            List<T> data = null;
            if (response.IsSuccessStatusCode)
            {
                string json = response.Content.ReadAsStringAsync().Result;
                Debug.WriteLine("### JSON REsult: " + json);
                ITraceWriter writer = new MemoryTraceWriter();
                JsonSerializerSettings settings = new JsonSerializerSettings
                {
                    TraceWriter = writer
                };
                try
                {
                    data = JsonConvert.DeserializeObject<List<T>>(json, settings);
                }
                catch (System.Exception ex)
                {
                    Debug.WriteLine("### Exception " + ex.Message);
                    Debug.WriteLine("### Trace Results: " + writer);

                }
            }
            return data;
        }

1 Ответ

0 голосов
/ 07 сентября 2018

Как вы уже поняли, вы должны использовать кастом IReferenceResolver.

Вы спрашивали в комментариях, как это можно сделать с несколькими типами. Вы можете использовать код распознавателя, найденный здесь , чтобы сделать это. Эта ссылка включает в себя полный пример:

Хотя он не использует несколько типов, легко продемонстрировать, как он использовался в таком случае.

Например, в дополнение к Person мы можем добавить тип Cat:

public class Cat
{
    public string Name {get; set;}
}

затем добавьте его как свойство Person:

public class Person
{
  public string Name { get; set;}
  public string PhoneNumber { get; set;}
  public Person Partner { get; set;}
  public Cat Cat { get; set;}
}

и затем измените JSON на:

[
  {
     ""$id"": ""Jane Doe"",
    ""Name"": ""Jane Doe"",
    ""Cat"": {
     ""$id"": ""Johny"",
      ""Name"": ""Johny"",
    },
    ""PhoneNumber"": ""(555)555-5555"",
    ""Partner"": {
      ""$id"": ""John Doe"",
      ""Name"": ""John Doe"",
      ""PhoneNumber"": ""(555)555-5555"",
      ""Partner"": {
        ""$ref"": ""Jane Doe""
      },
      ""Cat"": {
         ""$ref"": ""Johny""
        }
    }
  },
  {
    ""$ref"": ""John Doe"",
  }
]

и он будет работать так же, как в этой скрипке (обратите внимание, что вместо использования ReferenceResolverProvider (как в ссылке) он использует ReferenceResolver (что устарело), ​​и это потому, что он вызывает некоторую странную ошибку здесь, во всяком случае, вы должны использовать первый).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...