将 JSON 数组反序列化为字典,其中的键与 JSON 分开提供



我有一个这样的JSON文件:

{
    "price": ["123.50", "124.6", "126.30"],
    "order": ["23", "30", "20"]
}

我想Product填充我的对象:

public class Product {
  public Dictionary<string, Object> priceInfo;
  public Dictionary<string, Object> orderInfo;
}

我在每个 JSON 对象中都有每个值的描述(此处为数组),可能Product类中,例如:

String[] defPriceInfo = {"price", "avgprice", "maxprice"};

最后,我将使用 priceInfo.TryGetValue("avgprice", ...) 访问Product对象的这些值,这将返回给我的值

124,6

我在堆栈溢出中搜索,但没有找到类似的问题。实际上我试图覆盖JsonConverter.ReadJson但没有奏效;问题是我想要的个性化"钥匙"。

编辑1:我有这个方法ReadJson()但这是错误的。

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            object res = new Object();
            var tokenType = reader.TokenType;
            if (tokenType == JsonToken.StartObject)
            {
                 object obj = serializer.Deserialize(reader);
                 res = new Dictionary<string, string>();
            }
            else if (tokenType == JsonToken.StartArray)
            {
                res = serializer.Deserialize(reader);
            }
            return res;
        }

下面是使用自定义JsonConverter作为通用解决方案的一种方法。 这个想法是,你设置一个公共的、静态的、只读的字符串数组,其中包含你想要专门处理的每个字典的键,然后用一个[JsonConverter]属性标记每个字典字段,该属性指定在哪里可以找到包含键数组的静态字段。 然后,转换器使用指定的键从 JSON 数组填充字典。 (请注意,如果 JSON 数组属性名称与类中的字典成员名称不同,则还需要一个 [JsonProperty] 属性将它们绑定在一起。

以下是您在类Product设置示例的方法:

public class Product
{
    public static readonly string[] defPriceInfo = { "price", "avgprice", "maxprice" };
    public static readonly string[] defOrderInfo = { "first", "second", "third" };
    [JsonProperty("price")]
    [JsonConverter(typeof(ArrayToDictionaryConverter), typeof(Product), "defPriceInfo")]
    public Dictionary<string, object> priceInfo;
    [JsonProperty("order")]
    [JsonConverter(typeof(ArrayToDictionaryConverter), typeof(Product), "defOrderInfo")]
    public Dictionary<string, object> orderInfo;
}

这是自定义ArrayToDictionaryConverter的代码:

class ArrayToDictionaryConverter : JsonConverter
{
    private string[] keysArray;
    public ArrayToDictionaryConverter(Type containingObjectType, string keysArrayFieldName)
    {
        FieldInfo field = containingObjectType.GetField(keysArrayFieldName);
        if (field == null)
            throw new Exception("Could not find " + keysArrayFieldName + " field on type " + containingObjectType.Name + ".");
        if (!field.Attributes.HasFlag(FieldAttributes.Static) || field.FieldType != typeof(String[]))
            throw new Exception("The " + keysArrayFieldName + " field on " + containingObjectType.Name + " must be declared as static string[].");
        keysArray = (string[])field.GetValue(null);
    }
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Dictionary<string, object>));
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JArray array = JArray.Load(reader);
        Dictionary<string, object> dict = new Dictionary<string, object>();
        for (int i = 0; i < array.Count; i++)
        {
            string key = i < keysArray.Length ? keysArray[i] : "key" + i;
            dict.Add(key, (string)array[i]);
        }
        return dict;
    }
    public override bool CanWrite
    {
        get { return false; }
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

这是一个快速演示,展示了它是如何工作的:

using System;
using System.Collections.Generic;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class Program
{
    public static void Main()
    {
        string json = @"
            {
                ""price"": [""123.50"", ""124.6"", ""126.30""],
                ""order"": [""23"", ""30"", ""20""]
            }";
        try
        {
            Product prod = JsonConvert.DeserializeObject<Product>(json);
            foreach (var kvp in prod.priceInfo)
            {
                Console.WriteLine(kvp.Key + ": " + kvp.Value);
            }
            foreach (var kvp in prod.orderInfo)
            {
                Console.WriteLine(kvp.Key + ": " + kvp.Value);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
            if (e.InnerException != null) Console.WriteLine(e.InnerException.Message);
        }
    }
}

输出:

price: 123.50
avgprice: 124.6
maxprice: 126.30
first: 23
second: 30
third: 20

您可以通过首先将 JSON 反序列化为 POCO 来做到这一点,例如使用这样的类:

public class TempProduct 
{
  public Price price {get; set;}
  public Order order {get; set;}
  public class Price
  {
    public string price {get; set;}
    public string avgprice {get; set;}
    public string maxprice {get; set;}
  }
  public class Order
  {
    public string orderType1 {get; set;}
    public string orderType2 {get; set;}
    public string orderType3 {get; set;}
  }
}

然后,您可以从中填充您的产品类,例如

var prod = new Product();
prod.priceInfo = new Dictionary<string,Object>();
prod.priceInfo.Add("price", tempProd.price.price);
prod.priceInfo.Add("avgprice", tempProd.price.avgprice);
prod.priceInfo.Add("maxprice", tempProd.price.maxprice);

相关内容

  • 没有找到相关文章

最新更新