Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将JSON数组反序列化到字典中,其中的键与JSON单独提供_C#_Json_Dictionary_Json.net_Deserialization - Fatal编程技术网

C# 将JSON数组反序列化到字典中,其中的键与JSON单独提供

C# 将JSON数组反序列化到字典中,其中的键与JSON单独提供,c#,json,dictionary,json.net,deserialization,C#,Json,Dictionary,Json.net,Deserialization,我有一个JSON文件,如下所示: { "price": ["123.50", "124.6", "126.30"], "order": ["23", "30", "20"] } 我想填充我的对象产品: public class Product { public Dictionary<string, Object> priceInfo; public Dictionary<string, Object> orderInfo; } 最后,我将使用p

我有一个JSON文件,如下所示:

{
    "price": ["123.50", "124.6", "126.30"],
    "order": ["23", "30", "20"]
}
我想填充我的对象
产品

public class Product {
  public Dictionary<string, Object> priceInfo;
  public Dictionary<string, Object> orderInfo;
}
最后,我将使用
priceInfo.TryGetValue(“avgprice”,…)
访问
Product
对象的这些值,该值将返回给我

124.6

我在堆栈溢出中进行了搜索,但没有发现类似的问题。 实际上,我试图重写
JsonConverter.ReadJson
,但没有成功;问题是我想要的个性化“钥匙”

Edit1:我为
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;
        }
public override object ReadJson(JsonReader reader,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
object res=新对象();
var tokenType=reader.tokenType;
if(tokenType==JsonToken.StartObject)
{
object obj=序列化程序。反序列化(读取器);
res=新字典();
}
else if(tokenType==JsonToken.StartArray)
{
res=序列化程序。反序列化(读取器);
}
返回res;
}

您可以首先将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);
var prod=新产品();
prod.priceInfo=新字典();
产品价格信息添加(“价格”,临时产品价格);
prod.priceInfo.Add(“avgprice”,temprod.price.avgprice);
添加(“maxprice”,tempProd.price.maxprice);

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

下面是如何设置示例
产品
类:

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;
}
下面是一个快速演示,展示了它的工作原理:

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

你所说的可能在项目类中是什么意思?你的问题中没有
类。你是说
产品
类吗?如果是这样的话,您能给出一个您想以这种方式序列化和反序列化的类的示例,以及您在
ReadJson()
中迄今为止所尝试的方法吗?是的,很抱歉我按产品逐项更改了错误。我的意思是“也许”不是最好的解决办法。但事实上我看到的就是这个解决方案。我还想用文件加载信息。我将发布我尝试过的内容。我尝试的解决方案的问题是,我不知道如何在类中为我读取的每个值传递“键”描述符。@dbc我添加了我的示例,但这完全是错误的。我不明白这是如何工作的,相同的
defPriceInfo
键将用于两个JSON数组,或者您会为
order
数组使用不同的一组键吗?@BrianRogers不只是用于PriceInfo,我想另一个json数组应该有“defOrderInfo”。我不确定这个解决方案是否适合我的问题。我不想让类成倍增加,因为我想让类成为泛型。谢谢,但我有一个错误,因为在中添加了对附加参数的“JsonConverterAttribute构造函数没有3个参数”支持(2014年10月20日)。如果您使用的是旧版本,则需要升级。到现在为止是8.0.3。
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