Вызовите JsonConvert.DeserializeObject, если вы не знаете тип данных? - PullRequest
0 голосов
/ 30 октября 2018

У меня есть программа 3rdParty, из которой я получаю данные JOSN. Json может быть представлен двумя способами, и я создал два класса для представления двух сообщений JSON, используя http://json2csharp.com/

public class Data1
{
    public Content1 content { get; set; }

    public string name { get; set; }

    public string address { get; set; }

    public string age { get; set; }
}


public class Data2
{
    public Content2 content { get; set; }

    public string name { get; set; }

    public string address { get; set; }

    public string age { get; set; }
}

Они одинаковы, кроме Content1 и Content2 (у меня есть для них также классы).

Я хочу десериализовать данные следующим образом:

var object1 = JsonConvert.DeserializeObject<Data1>(message1);
var object2 = JsonConvert.DeserializeObject<Data2>(message2);

Но я не знаю, какое сообщение я получу, так как я могу создать один класс, который я могу десериализовать и затем использовать.

Я посмотрел на этот пример https://www.jerriepelser.com/blog/deserialize-different-json-object-same-class/ и попытался создать суперкласс, который имеет:

[JsonConverter(typeof(SuperData))] 

но я не уверен, как реализовать функцию ReadJson .

Проверять ли поступающие данные и определять, имеет ли контент тип Content1 или Content2 ? Если да, то как мне это сделать?

Как тогда узнать, какой класс был десериализован, чтобы я мог узнать, проверять ли он другой контент?

Вот этот JSON: Data1

{
    "content": {
    "person_id": "1234",
    "timestamp": "2018-10-30 13:09:04.382885",
    "features": "old, cranky"
  },

  "name": "JoeBloggs",
  "address": "address1",    
  "age": 31,    
}

Data2

{
  "content": 
  {
    "detections": 1,

    "detection_boxes": [
      {
        "name": "JoeBloggs",
        "bbox": [
          1988.162842886987,
          -20.466329557695307,
          2662.417876180017,
          846.0808020362452
        ],
        "id": 3610
      }
    ],

    "timestamp": "2018-10-30 13:09:07.171000",
    ]
  },

  "name": "JoeBloggs",
  "address": "address1",    
  "age": 31,    
}

Я пробовал это:

[JsonConverter(typeof(MyDataConverter))]
public class MegaData
{
    public object content { get; set; }

    public string name { get; set; }

    public string address { get; set; }

    public string age { get; set; }
}

MyDataConverter имеет следующее:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var jObject = JObject.Load(reader);
        var content = jObject["message_content"];
        if (content["person_id"] != null)
        {
            return jObject.ToObject<Data1>();
        }
        else
        {
            return jObject.ToObject<Data2>();
        }
    }

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

var alert = JsonConvert.DeserializeObject<MegaData>(message1); <-- EXCEPTION

**Unable to cast object of type 'Data1' to type 'MegaData'.**

Как должен выглядеть мой класс MegaData, чтобы это работало ??

Ответы [ 2 ]

0 голосов
/ 30 октября 2018

Таким образом, вы можете создать собственный конвертер, полученный из JsonConverter, и в ReadJson вы сделаете что-то вроде этого:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    var jObject = JObject.Load(reader);
    var content = jObject["content"];
    if (content["person_id"] != null) 
    {
        return jObject.ToObject<Data1>();
    }
    else
    {
        return jObject.ToObject<Data2>();
    }
}

Если вы на самом деле не пишете JSON, вы можете пропустить метод WriteJson (пусть он выбрасывает NotImplementedException) и установить CanWrite для возврата false (так что он никогда не будет вызываться в любом случае) *. * 1010

0 голосов
/ 30 октября 2018

Почему вы не можете иметь один класс с типом и десериализацией до этого типа

public class DetectionBox
{
    public string name { get; set; }
    public List<double> bbox { get; set; }
    public int id { get; set; }
}

public class Content
{
    public int detections { get; set; }
    public List<DetectionBox> detection_boxes { get; set; }
    public string timestamp { get; set; }
    public string person_id { get; set; }
    public string features { get; set; }
}

public class Data
{
    public Content content { get; set; }
    public string name { get; set; }
    public string address { get; set; }
    public int age { get; set; }
}


Data data = JsonConvert.DeserializeObject<Data>(json);
...