Десериализовать свойство в другой класс на основе другого свойства c#

#c# #json #json.net #deserialization #system.text.json

#c# #json #json.net #десериализация #system.text.json

Вопрос:

Я знаю, что есть много похожих вопросов по SO, однако все те, которые я нашел, требуют общего базового класса для работы.

С потоком данных JSON, подобных этому:

 [
  {
    "webhookType": "order",
    "data": {
      "id": "eeiefj393",
      "orderProperty": "Value"
    }
  },
  {
    "webhookType": "customer",
    "data": {
      "id": 29238,
      "customerProperty": "Value"
    }
  }
]
  

Я хочу десериализовать это в два контейнера, List<Customer> и List<Order> . Где два класса следующие:

 class Order
{
    public string Id { get; set; }
    public string OrderProperty { get; set; }
    [...]
}

class Customer
{
    public long Id { get; set; }
    public string CustomerProperty { get; set; }
    [...]
}
  

Могут быть общие имена свойств, однако между этими двумя классами нет общих свойств тип, и поэтому решения, связанные с подклассом, не работают для меня.

Ответ №1:

Вам нужно создать JsonConverter .

DataConverter

 public class WebHookConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.StartObject)
        {
            JObject item = JObject.Load(reader);

            if (item["webhookType"].Value<string>() == "order")
            {
                var webhook = new WebHook
                {
                    Type = item["webhookType"].Value<string>(),
                    Data = item["data"].ToObject<Order>()
                };

                return webhook;
            }
            else if (item["webhookType"].Value<string>() == "customer")
            {
                var webhook = new WebHook
                {
                    Type = item["webhookType"].Value<string>(),
                    Data = item["data"].ToObject<Customer>()
                };

                return webhook;
            }
        }

        return null;
    }

    public override bool CanConvert(Type objectType)
    {
        throw new NotImplementedException();
    }
}
  

Объекты

 [JsonConverter(typeof(WebHookConverter))]
public class WebHook
{
    [JsonProperty("webhookType")]
    public string Type { get; set; }
    public object Data { get; set; }
}

public class Order
{
    public string Id { get; set; }

    [JsonProperty("orderProperty")]
    public string Property { get; set; }
}

public class Customer
{
    public long Id { get; set; }

    [JsonProperty("customerProperty")]
    public string Property { get; set; }
}
  

Сериализация

 var json = File.ReadAllText("json1.json");
var obj = JsonConvert.DeserializeObject<List<WebHook>>(json);

var orderList = obj.Where(o => o.Type == "order").Select(o => o.Data).ToList();
var customerList = obj.Where(o => o.Type == "customer").Select(o => o.Data).ToList();
  

Вывод:
введите описание изображения здесь

Комментарии:

1. Ах, это здорово. Я просто не смог найти пример JsonConverter, который не использовал базовые классы.