【问题标题】:JSON.net serializes a json array into a JArray when the destination is an object. How can I change that?当目标是对象时,JSON.net 将 json 数组序列化为 JArray。我该如何改变呢?
【发布时间】:2016-11-30 08:40:46
【问题描述】:

我有一个单级 json,我想使用 Json.Net 将其反序列化为 Dictionary<string,object>

字典的值可以是原始、字符串或(原始\字符串)数组。

反序列化知道如何处理原语和字符串,但是当它到达原语数组时,它会将其反序列化为JArray(而不是原语数组)。

这是我的意思的一个小代码示例:

string jsonStr = @"{""obj"": 7, ""arr"": ['1','2','3']}"; 
Dictionary<string, object> dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonStr);

dict["obj"].GetType(); // long
dict["arr"].GetType(); // JArray. I would like this to be string[].

我正在寻找一种可以干预反序列化过程并创建原始数组而不是被JArray 卡住的方法。

我已经尝试使用JsonSerializerSettings 进行此操作,但无法确定。

【问题讨论】:

标签: c# arrays serialization json.net


【解决方案1】:

这是一个很老套的方法。我创建了一个自定义 JsonConverter 类,它接受 2 个通用参数:T1 和 T2。 T1 给出了数组的类型(在本例中为字符串),T2 给出了另一个对象的类型(在本例中为 long)。我假设我们基本上想要一个字典,但这部分肯定可以改进。

using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string jsonStr = @"{""obj"": 7, ""arr"": ['1','2','3']}";
            Dictionary<string, object> dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonStr, new SpecialConverter<string, long>());

            dict["obj"].GetType(); // long
            dict["arr"].GetType(); // string[].
        }

        class SpecialConverter<T1, T2> : JsonConverter
        {
            public override bool CanConvert(Type objectType)
            {
                return true;
            }

            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                JToken token = JToken.Load(reader);
                var result = new Dictionary<string, object>();
                if (result.GetType() == objectType)
                {
                    foreach (var item in token)
                    {
                        var prop = (JProperty)item;
                        if (prop.Value.Type == JTokenType.Array)
                        {
                            result.Add(prop.Name, prop.Value.ToObject<T1[]>());
                        }
                        else
                        {
                            result.Add(prop.Name, prop.Value.ToObject<T2>());
                        }
                    }

                    return result;
                }
                else
                {
                    return null;
                }
            }

            public override bool CanWrite
            {
                get { return false; }
            }

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

【讨论】:

  • 我的对象又大又复杂。您的解决方案实际上是重新编写序列化程序。 +1 努力,我一直在寻找更通用的东西,而不是重新编写 json 序列化程序。
  • @AmirPopovich 我不认为你可以比object [] 做得更好,除非你用json2csharp.com 之类的东西为你的JSON 对象创建类。
【解决方案2】:

它不转换为数组的原因是因为您告诉 JsonConvert 将其转换为 Dictionary&lt;string, object&gt; 而这正是它所做的基于它没有特定的 Object 来转换的事实to ,因此它“猜测”选择了 JArray,如果字典的值可以有多种类型,最好的办法是将其转换为动态对象。如果“arr”的值是数组,这将为您提供一个数组,如果该值是一个简单的字符串,则为您提供一个字符串。

string jsonStr = @"{""obj"": 7, ""arr"": ['1','2','3']}";
        dynamic dict = JsonConvert.DeserializeObject(jsonStr);
        var arr = dict.arr;
        string firstelement = arr[0]; // print "1"

【讨论】:

  • 我理解它没有按照我想要的方式转换它的原因。我试图以某种方式干预(也许通过转换器)以实现它。动态不是一个选项,因为它仍会将其保留为 JArray。还是谢谢!
  • Dynamic 不会将其保留为 JArray,而是将其转换为数组。
  • 是的。我刚刚检查过它是100%确定的。此行 fo 代码返回 true:dict["arr"].GetType() == typeof(JArray)
  • 道歉是的,你是对的,当你越过 var arr = dict.arr;类型是数组,但是当你得到类型时,它就变成了 JArray。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-15
  • 2013-08-14
  • 2014-08-22
  • 1970-01-01
相关资源
最近更新 更多