Newtonsoft JSon反序列化为原始类型 [英] Newtonsoft JSon Deserialize into Primitive type

查看:324
本文介绍了Newtonsoft JSon反序列化为原始类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C#程序中,我正在查询Web服务并以JSON形式返回返回流:

In my C# program, I am querying a webservice and getting a reply stream back in JSON that looks something like this:

{"val":12345.12},{"val":23456.23},{"val":34567.01},...

或,每个回复对象的值可能超过1:

or, with possibly more than 1 value per reply object:

{"val1":12345.12,"val2":1},{"val1":23456.23,"val2":3},....

我有以下代码利用 Newtonsoft.Json 库来解析流并执行一些操作在每个解析的对象上,一次一个:

And I have the following code utilizing the Newtonsoft.Json library that parses the stream and performs some action on each parsed object, one at a time:

public void ParseReply<T>(StreamReader sr, Action<T> action)
{
    using (var reader = new JsonTextReader(sr))
    {
        var ser = new JsonSerializer();

        while (reader.Read())
        {
            if (reader.TokenType == JsonToken.EndArray)
                break;
            action(ser.Deserialize<T>(reader));
        }
    }
}

因此,在第二个结果的情况下,我有以下代码:

So, in the case of the second result, I have the following code:

public class MyObject
{
    public double val1;
    public double val2;
}

然后:

myJson.ParseReply<MyObject>(sr, obj => ...);

工作完美.

但是,在第一个答复(每个对象1个值)的情况下,如果我尝试通过以下方式使用我的方法:

But, in the case of the first reply (1 value per object), if I try and use my method in the following way:

myJson.ParseReply<double>(sr, dbl => ...);

我收到一条错误消息:

Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Double' because the type requires a JSON primitive value (e.g. string, number, boolean, null) to deserialize correctly.
To fix this error either change the JSON to a JSON primitive value (e.g. string, number, boolean, null) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.

我真的迷失了/很好奇如何更新我的代码以能够正确解析这两个代码,我对这个错误消息有点迷茫.任何帮助将不胜感激!

I'm really lost / curious how I could update my code to be able to parse both of these correctly and I'm a bit lost on this error message. Any help would REALLY be appreciated!!

推荐答案

如果您更改静态方法以返回IEnumerable<T>而不是获取Action<T>,则可以将

If you change your static method to return an IEnumerable<T> rather than taking an Action<T>, you will be able to chain together Enumerable and LINQ to JSON methods in a very concise and natural way. Thus if you have:

public static class JsonExtensions
{
    public static IEnumerable<T> ParseArray<T>(this TextReader textReader)
    {
        using (var reader = new JsonTextReader(textReader))
        {
            bool inArray = false;
            var ser = JsonSerializer.CreateDefault();
            while (reader.Read())
            {
                if (reader.TokenType == JsonToken.Comment)
                    continue;
                if (reader.TokenType == JsonToken.StartArray && !inArray)
                {
                    inArray = true;
                    continue;
                }
                if (reader.TokenType == JsonToken.EndArray)
                    break;
                yield return ser.Deserialize<T>(reader);
            }
        }
    }

    public static IEnumerable<JToken> DescendantsAndSelf(this JToken node)
    {
        // This method should be present on JToken but is only present on JContainer.
        if (node == null)
            return Enumerable.Empty<JToken>();
        var container = node as JContainer;
        if (container != null)
            return container.DescendantsAndSelf();
        else
            return new[] { node };
    }

    public static bool IsNumeric(this JTokenType type) { return type == JTokenType.Integer || type == JTokenType.Float; }

    public static bool IsNumeric(this JToken token) { return token == null ? false : token.Type.IsNumeric(); }
}

您可以这样做:

        var json = @"[{""val"":12345.12},{""val"":23456.23},{""val"":34567.01}]";

        // Select all properties named "val" and transform their values to doubles.
        foreach (var val in new StringReader(json).ParseArray<JToken>()
            .Select(t => (double)t.SelectToken("val")))
        {
            Debug.WriteLine(val);
        }

        // Select all primitive numeric values
        foreach (var val in new StringReader(json).ParseArray<JToken>()
            .SelectMany(t => t.DescendantsAndSelf())
            .Where(t => t.IsNumeric())
            .Select(t => (double)t))
        {
            Debug.WriteLine(val);
        }

这篇关于Newtonsoft JSon反序列化为原始类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆