Вызовите JsonConvert.DeserializeObject, если вы не знаете тип данных?

У меня есть программа 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 ответа

Решение

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

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);

Таким образом, вы можете создать собственный конвертер, полученный из 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 (так что это никогда не будет называться в любом случае).

Другие вопросы по тегам