Json: 解析一个动态类型

Json: Parse a dynamic type

我正在尝试反序列化一些 Json:

{
    "name": "foo",
    "value": [ [ 1.2, 2.3, 4.5 ], [ 1.2, 2.3, 4.5 ] ]
}

进入此 C# class:

class Bar {
    public string name { get; set; }
    public object value { get; set; }
}

值是 object 类型,因为它可以是单个值或任何数组,...,值。

我试过使用原生 C# class:

string jsonString = @"{
    ""name"": ""foo"",
    ""value"": [ [ 1.2, 2.3, 4.5 ], [ 1.2, 2.3, 4.5 ] ]
}";
var data1 = new JavaScriptSerializer().Deserialize<Bar>(jsonString).value;

data1object[]object[],实际上是 decimal。问题是:我需要它们是 doubles.

所以我尝试使用 Json.NET 库:

var data2 = JsonConvert.DeserializeObject<Bar>(
    jsonString,
    new JsonSerializerSettings { FloatParseHandling = FloatParseHandling.Double }
).value;

现在最终值是 double 类型,但我丢失了对象数组的结构,取而代之的是 JArray of JArray of double

所以我的问题是:是否可以配置本机 JavaScriptSerializer class 以获得 doubles 而不是 decimals 是否可以制作 Json.NET return 个 objects 数组?

如果您的 Json for Value 属性 始终是一个数组(即使单个值是一个数组) - 那么您始终可以反序列化为 object[] for 属性。这也将处理数组的数组。

    {"name": "foo","value": [1.2]};

    class Bar
    {
        public string name { get; set; }
        public object[] value { get; set; }
    }

如果不是这种情况,它可以是一个值本身,也可以是数组或数组的数组,那么您可能需要求助于实施自定义 JsonConverter 来满足您的业务需求。

https://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm

由于value的类型不固定我们可以说它是动态的,我们可以在C#中使用dynamic关键字来表示属性:

class Bar
{
    public string name { get; set; }
    public dynamic value { get; set; }
}

这里我们在运行时发现value的类型并相应地处理它。你可以自由地坚持使用 JavaScriptSerializer,就像我在这里所做的那样,或者如果你愿意,你可以看看用 Newtonsoft 实现类似的东西:

List<double> ParseFoo(string jsonString)
{
    var data1 = new JavaScriptSerializer().Deserialize<Bar>(jsonString).value;
    var r = new List<double>();

    // We can handle a single value, an array, or an array of arrays:
    var array = data1 as object[];
    if (array != null)
    {
        foreach (object obj in array)
        {
            decimal? number = obj as decimal?;
            if (number.HasValue)
                r.Add((double)number.Value);
            else
                r.AddRange((obj as object[]).Cast<decimal>().Select(d => (double)d));
        }
    } else
    {
        r.Add((double)data1);
    }

    return r;
}

测试:

void Main()
{
    string jsonString = @"{
    ""name"": ""foo"",
    ""value"": [ [ 1.2, 2.3, 4.5 ], [ 1.2, 2.3, 4.5 ] ]
    }";

    Console.WriteLine(ParseFoo(jsonString));

    jsonString = @"{
    ""name"": ""foo"",
    ""value"": [ 1.2, 2.3, 4.5 ]
    }";

    Console.WriteLine(ParseFoo(jsonString));

    jsonString = @"{
    ""name"": ""foo"",
    ""value"": 2.7
    }";

    Console.WriteLine(ParseFoo(jsonString));
}

控制台输出: