JSON 反序列化 - 将常见类型的对象转换为列表

问题描述 投票:0回答:2

我有以下来自 API 的 JSON

{
  "rates": {
    "EURGBP": {
      "rate": 0.871625,
      "timestamp": 1619193484
    },
    "USDJPY": {
      "rate": 107.939463,
      "timestamp": 1619193484
    }
  }
}

我想创建类来反序列化这个 JSON。如果我进行 JSON 到 C# 的转换,我会得到以下 C# 类:

public class Rates
{
    public EURGBP EURGBP { get; set; }
    public USDJPY USDJPY { get; set; }
}

public class EURGBP
{
    public double rate { get; set; }
    public int timestamp { get; set; }
}

public class USDJPY
{
    public double rate { get; set; }
    public int timestamp { get; set; }
}

问题是可能会有更多对象进入

rates
对象。喜欢

"NZDUSD": {
    "rate": 0.718962,
    "timestamp": 1619198884
}

在这种情况下,我不会有一个类

NZDUSD
来反序列化新对象。

那么我是否可以有一个泛型类,使用它可以反序列化

rates
下的对象,因为它们将具有共同的属性?

我可以在反序列化期间或之后将

rates
下的对象转换为
List
Dictionary
吗?

c# json .net deserialization
2个回答
3
投票

您可以使用字典创建这样的对象模型:

        public class Result
        {
            public IDictionary<string, Rate> Rates { get; set; }
        }

        public class Rate
        {
            public double rate { get; set; }
            public int timestamp { get; set; }
        }

然后使用Newtonsoft反序列化:

var values = Newtonsoft.Json.JsonConvert.DeserializeObject<Result>(json);

1
投票

那么我是否可以有一个泛型类,使用它可以反序列化速率下的对象,因为它们将具有共同的属性?

有几种不同的方法可以实现此目的,Connell 已经提供了其中一种方法。另一种方法是创建您自己的

JsonConverter
。下面我将向您展示如何做到这一点。

-创建一个名为:

CurrencyConverter
的新类,确保它如下所示:

  using System;
  using System.Collections.Generic;
  using Newtonsoft.Json;
  using Newtonsoft.Json.Linq;
  
  public class CurrencyConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType) => typeof(List<Rate>).IsAssignableFrom(objectType);

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            List<Rate> rates = new List<Rate>();

            if (reader.TokenType == JsonToken.StartObject)
            {
                JToken token = JToken.Load(reader);
                IEnumerable<JToken> tokenChildren = token.Root.First?.First?.Children();
                foreach (JToken child in tokenChildren)
                {
                    double dblRate = GetValue(child.First, "rate", 0d);
                    int intTimeStamp = GetValue(child.First, "timestamp", 0);
                    rates.Add(new Rate() { RateName = ((JProperty)child).Name, rate = dblRate, Timestamp = intTimeStamp });
                }
            }

            return rates;
        }

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

        public T GetValue<T>(JToken jToken, string key, T defaultValue = default(T))
        {
            dynamic ret = jToken[key];
            if (ret == null) return defaultValue;
            if (ret is JObject) return JsonConvert.DeserializeObject<T>(ret.ToString());
            return (T)ret;
        }
    }

-接下来创建一个名为

Rate
的新类:

public class Rate
{
    public string RateName { get; set; }
    public double rate { get; set; }
    public int Timestamp { get; set; }
}

-最后反序列化你的

json

 JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings();
 jsonSerializerSettings.Converters.Add(new CurrencyConverter());
 var jsonOutput = JsonConvert.DeserializeObject<List<Rate>>(json, jsonSerializerSettings);

使用您提供的

json
,我得到了一个包含两个
Rate
对象的列表。

© www.soinside.com 2019 - 2024. All rights reserved.