Converting arbitrary json response to list of “things”

为君一笑 提交于 2019-12-06 04:25:46

Since Json.NET is licensed under the MIT license, you could adapt the logic of ExpandoObjectConverter to fit your needs, and create the following method:

public static class JsonExtensions
{
    public static IQueryable<object> ReadJsonAsDynamicQueryable(string json, JsonSerializerSettings settings = null)
    {
        var serializer = JsonSerializer.CreateDefault(settings);
        using (StringReader sr = new StringReader(json))
        using (JsonTextReader reader = new JsonTextReader(sr))
        {
            var root = JsonExtensions.ReadJsonAsDynamicQueryable(reader, serializer);
            return root;
        }
    }

    public static IQueryable<dynamic> ReadJsonAsDynamicQueryable(JsonReader reader, JsonSerializer serializer)
    {
        dynamic obj;

        if (!TryReadJsonAsDynamic(reader, serializer, out obj) || obj == null)
            return Enumerable.Empty<dynamic>().AsQueryable();

        var list = obj as IList<dynamic> ?? new [] { obj };

        return list.AsQueryable();
    }

    public static bool TryReadJsonAsDynamic(JsonReader reader, JsonSerializer serializer, out dynamic obj)
    {
        // Adapted from:
        // https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs
        // License:
        // https://github.com/JamesNK/Newtonsoft.Json/blob/master/LICENSE.md

        if (reader.TokenType == JsonToken.None)
            if (!reader.Read())
            {
                obj = null;
                return false;
            }

        switch (reader.TokenType)
        {
            case JsonToken.StartArray:
                var list = new List<dynamic>();
                ReadList(reader,
                    (r) =>
                    {
                        dynamic item;
                        if (TryReadJsonAsDynamic(reader, serializer, out item))
                            list.Add(item);
                    });
                obj = list;
                return true;

            case JsonToken.StartObject:
                obj = serializer.Deserialize<ExpandoObject>(reader);
                return true;

            default:
                if (reader.TokenType.IsPrimitiveToken())
                {
                    obj = reader.Value;
                    return true;
                }
                else
                {
                    throw new JsonSerializationException("Unknown token: " + reader.TokenType);
                }
        }
    }

    static void ReadList(this JsonReader reader, Action<JsonReader> readValue)
    {
        while (reader.Read())
        {
            switch (reader.TokenType)
            {
                case JsonToken.Comment:
                    break;
                default:
                    readValue(reader);
                    break;
                case JsonToken.EndArray:
                    return;
            }
        }
        throw new JsonSerializationException("Unexpected end when reading List.");
    }

    public static bool IsPrimitiveToken(this JsonToken token)
    {
        switch (token)
        {
            case JsonToken.Integer:
            case JsonToken.Float:
            case JsonToken.String:
            case JsonToken.Boolean:
            case JsonToken.Undefined:
            case JsonToken.Null:
            case JsonToken.Date:
            case JsonToken.Bytes:
                return true;
            default:
                return false;
        }
    }
}

Then use it like:

protected IQueryable<dynamic> TestMethod(string r)
{
    return JsonExtensions.ReadJsonAsDynamicQueryable(r);
}

Or, you could call ReadJsonAsDynamicQueryable from within the ReadJson() method of a custom JsonConverter that you create.

Sample fiddle.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!