Как использовать свойство JProperty Name при десериализации объекта с помощью NewtonSoft? - PullRequest
1 голос
/ 07 августа 2020

Я пытаюсь десериализовать объект JSON и хотел бы использовать его имя свойства в качестве атрибута, но не знаю, как это сделать.

Вот мои классы модели:

public partial class Questions
{
    [JsonProperty("timestamp")]
    public DateTimeOffset TimeStamp { get; set; }

    [JsonProperty("choices")]
    public Choices choices { get; set; }
}

public partial class Choices
{
    [JsonProperty("choices")]
    public string[] choices { get; set; }
}

Вот связанный JSON:

{
  "id": "5e6106600066d227a231ceb8",
  "complete": null,
  "questions": {
    "5e60af61a7be775b0d31ea77": {
      "timeStamp": "2020-03-05T15:01:56.000000Z",
      "choices": [
        "dsbb"
      ]
    },
    "5e60af66a7be775b0d31ea78": {
      "timeStamp": "2020-03-05T15:02:02.000000Z",
      "choices": [
        "9999999999"
      ]
    },
    "5e60af76dd15333d1727ce09": {
      "timeStamp": "2020-03-05T15:02:11.000000Z",
      "choices": [
        "lj@test.com"
      ]
    },
    "5e60afeeb406ed608058d045": {
      "timeStamp": "2020-03-05T15:02:15.000000Z",
      "choices": [
        0
      ]
    },
    "5e5d282331808f44ce4b0b76": {
      "timeStamp": "2020-03-05T15:02:22.000000Z",
      "choices": [
        0
      ]
    },
    "5e5cec17ae23a40b0c645614": {
      "timeStamp": "2020-03-05T15:02:29.000000Z",
      "choices": [
        0
      ]
    },
    "5e5d08d235bf95782b049cb3": {
      "timeStamp": "2020-03-05T15:02:34.000000Z",
      "choices": [
        2
      ]
    },
    "5e5d0a05a0be6b6533195f17": {
      "timeStamp": "2020-03-05T15:02:43.000000Z",
      "choices": [
        0
      ]
    },
    "5e5cecdcf3c27f611b3df2fa": {
      "timeStamp": "2020-03-05T15:03:01.000000Z",
      "choices": [
        "100"
      ]
    },
    "5e5cedd7949da059190f2146": {
      "timeStamp": "2020-03-05T15:03:10.000000Z",
      "choices": [
        1,
        3,
        4
      ]
    },
    "5e60e8e899017615e27ad107": {
      "timeStamp": "2020-03-05T15:03:15.000000Z",
      "choices": [
        0
      ]
    },
    "5e60e95d479b812cb4777b2f": {
      "timeStamp": "2020-03-05T15:03:22.000000Z",
      "choices": [
        0
      ]
    },
    "5e60e9feff05631d3b0585d8": {
      "timeStamp": "2020-03-05T15:03:59.000000Z",
      "choices": [
        "fveg"
      ]
    }
  },
  "ip_address": "188.165.111.130",
  "created_at": "2020-03-05T14:02:08.621000Z",
  "updated_at": "2020-03-05T14:04:21.995000Z"
}

И, наконец, мой код привязки:

JObject respondants= JObject.Parse(json);
IList<JToken> questions = new List<JToken>();
questions = respondants["questions"].Children().ToList();
foreach(JToken q in questions){
    Questions question = q.ToObject<Questions>();
}

Пытаясь сделать это, я сталкиваюсь со следующим исключение:

Newtonsoft. Json .JsonSerializationException 's'est produite dans System.Private.CoreLib.dll:' Неожиданный токен при десериализации объекта: PropertyName

Любой идея?

Ответы [ 3 ]

0 голосов
/ 07 августа 2020

Однажды ответив, я понял, что неправильно понял ваш вопрос. Надеюсь, этот попадет в цель.

Ваши вопросы json содержит объекты с такими именами, как «5e60af61a7be775b0d31ea77», и для них нет подходящих классов в ваших определениях, поэтому они являются неожиданными.

Вам необходимо использовать класс JToken (или класс JObject) и из этого привести объект вопроса к свойству, которое явно имеет атрибуты имени и значения, к которым вы можете получить доступ, чтобы получить имя объекта «5e60af61a7be775b0d31ea77».

Затем вы можете использовать первый дочерний элемент для получения сведений о Timestamp и choices

JToken respondants = JToken.Parse(json);
IList<JToken> questions = new List<JToken>();
List<Question> replies = new List<Question>();

questions = respondants["questions"].Children().ToList();
foreach (JToken q in questions)
{
   Question question = new Question
   {
       QuestionId = (q as JProperty).Name,
       QuestionDetail = q.Children().First().ToObject<Detail>()
   };
   replies.Add(question);
}



public class Question
{
    public string QuestionId { get; set; }
    [JsonProperty("timestamp")]
    public Detail QuestionDetail { get; set; }
}

public class Detail
{
    [JsonProperty("timestamp")]
    public DateTimeOffset TimeStamp { get; set; }

    [JsonProperty("choices")]
    public List<string> Choices { get; set; }
}

Я также немного упростил определение вашего класса, и, вероятно, вам нужен список строк, а не массив струн. Массив или список: когда использовать?

Также обратите внимание, что ваш json не имеет очень согласованной модели, хотя он действителен json. В 4-м вопросе массив 'choices' переключается с массива строк на числа.

0 голосов
/ 07 августа 2020

Похоже, вы хотите использовать классы модели для десериализации данных, но у вас возникли проблемы с обработкой шестнадцатеричных имен свойств динамического c внутри объекта questions. Чтобы обойти это, вы пытаетесь использовать JObjects / JTokens. Хотя этот подход будет работать, если вы сделаете это правильно, есть более простой способ. Вы можете использовать Dictionary<string, Question> в своей модели для обработки имен свойств динамического c. Сделайте ваши классы такими:

public class RootObject
{
    [JsonProperty("id")]
    public string Id { get; set; }

    [JsonProperty("questions")]
    public Dictionary<string, Question> Questions { get; set; }

    [JsonProperty("ip_address")]
    public string IpAddress { get; set; }

    [JsonProperty("created_at")]
    public DateTimeOffset CreatedAt { get; set; }

    [JsonProperty("updated_at")]
    public DateTimeOffset UpdatedAt { get; set; }
}

public partial class Questions
{
    [JsonProperty("timestamp")]
    public DateTimeOffset TimeStamp { get; set; }

    [JsonProperty("choices")]
    public List<string> Choices { get; set; }
}

Затем вы можете десериализовать следующим образом:

var root = JsonConvert.DeserializeObject<RootObject>(json);

Вот рабочая демонстрация: https://dotnetfiddle.net/VE7upc

0 голосов
/ 07 августа 2020

Вы можете подготовить образец скрипки перед тем, как попросить.

        string json = "{\"id\":\"5e6106600066d227a231ceb8\",\"complete\":null,\"questions\":{\"5e60af61a7be775b0d31ea77\":{\"timeStamp\":\"2020-03-05T15:01:56.000000Z\",\"choices\":[\"dsbb\"]},\"5e60af66a7be775b0d31ea78\":{\"timeStamp\":\"2020-03-05T15:02:02.000000Z\",\"choices\":[\"9999999999\"]},\"5e60af76dd15333d1727ce09\":{\"timeStamp\":\"2020-03-05T15:02:11.000000Z\",\"choices\":[\"lj@test.com\"]},\"5e60afeeb406ed608058d045\":{\"timeStamp\":\"2020-03-05T15:02:15.000000Z\",\"choices\":[0]},\"5e5d282331808f44ce4b0b76\":{\"timeStamp\":\"2020-03-05T15:02:22.000000Z\",\"choices\":[0]},\"5e5cec17ae23a40b0c645614\":{\"timeStamp\":\"2020-03-05T15:02:29.000000Z\",\"choices\":[0]},\"5e5d08d235bf95782b049cb3\":{\"timeStamp\":\"2020-03-05T15:02:34.000000Z\",\"choices\":[2]},\"5e5d0a05a0be6b6533195f17\":{\"timeStamp\":\"2020-03-05T15:02:43.000000Z\",\"choices\":[0]},\"5e5cecdcf3c27f611b3df2fa\":{\"timeStamp\":\"2020-03-05T15:03:01.000000Z\",\"choices\":[\"100\"]},\"5e5cedd7949da059190f2146\":{\"timeStamp\":\"2020-03-05T15:03:10.000000Z\",\"choices\":[1,3,4]},\"5e60e8e899017615e27ad107\":{\"timeStamp\":\"2020-03-05T15:03:15.000000Z\",\"choices\":[0]},\"5e60e95d479b812cb4777b2f\":{\"timeStamp\":\"2020-03-05T15:03:22.000000Z\",\"choices\":[0]},\"5e60e9feff05631d3b0585d8\":{\"timeStamp\":\"2020-03-05T15:03:59.000000Z\",\"choices\":[\"fveg\"]}},\"ip_address\":\"188.165.111.130\",\"created_at\":\"2020-03-05T14:02:08.621000Z\",\"updated_at\":\"2020-03-05T14:04:21.995000Z\"}";
        JObject respondants = JObject.Parse(json);
        foreach (JProperty x in respondants["questions"])
        { 
            Console.WriteLine(x.Name);
            Console.WriteLine(x.Value);
        }

Вот так: https://dotnetfiddle.net/f5jEgS

...