.NET中的JObject.SelectToken等效项 [英] JObject.SelectToken Equivalent in .NET

查看:121
本文介绍了.NET中的JObject.SelectToken等效项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要删除JSON的外部节点.因此,一个例子是:

I need to remove the outer node of a JSON. So an example would be :

{
    app: {
       ...
    }
}

关于如何删除外部节点的任何想法,所以我们只能得到

Any ideas on how to remove the outer node, so we get only

{
   ...
}

没有(仅使用.NET Framework(C#)中的工具)使用JSON.NET.

WITHOUT using JSON.NET, only tools in the .NET Framework (C#).

在Json.NET中,我使用了:

In Json.NET I used:

JObject.Parse(json).SelectToken("app").ToString();

或者,DataContractJsonSerializer的任何配置也可以使用,以便在反序列化时忽略根.我现在进行反序列化的方法是:

Alternatively, any configuration of the DataContractJsonSerializer, so that it ignores the root when deserializing, would also work. The way I do the desrialization now is:

protected T DeserializeJsonString<T>(string jsonString)
        {
            T tempObject = default(T);

            using (var memoryStream = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
            {
                var serializer = new DataContractJsonSerializer(typeof(T));
                tempObject = (T)serializer.ReadObject(memoryStream);
            }

            return tempObject;
        }

请注意,根对象的属性名称可能因大小写而异.例如,它可以是"transaction".

Note that the root object's property name can differ from case to case. For example it can be "transaction".

感谢您的任何建议.

推荐答案

没有等效于

There is no equivalent to SelectToken built into .Net. But if you simply want to unwrap an outer root node and do not know the node name in advance, you have the following options.

  1. 如果您使用的是.Net 4.5或更高版本,则可以使用

  1. If you are using .Net 4.5 or later, you can deserialize to a Dictionary<string, T> with DataContractJsonSerializer.UseSimpleDictionaryFormat = true:

protected T DeserializeNestedJsonString<T>(string jsonString)
{
    using (var memoryStream = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
    {
        var serializer = new DataContractJsonSerializer(typeof(Dictionary<string, T>));
        serializer.UseSimpleDictionaryFormat = true;
        var dictionary = (Dictionary<string, T>)serializer.ReadObject(memoryStream);
        if (dictionary == null || dictionary.Count == 0)
            return default(T);
        else if (dictionary.Count == 1)
            return dictionary.Values.Single();
        else
        {
            throw new InvalidOperationException("Root object has too many properties");
        }
    }
}

请注意,如果您的根对象包含多个属性,则不能反序列化为 Dictionary<TKey, TValue> 以获取 first 属性,因为此类中各项的顺序未定义.

Note that if your root object contains more than one property, you cannot deserialize to a Dictionary<TKey, TValue> to get the first property since the order of the items in this class is undefined.

在任何支持数据协定序列化程序的.Net版本上,您都可以利用DataContractJsonSerializer继承自

On any version of .Net that supports the data contract serializers, you can take advantage of the fact that DataContractJsonSerializer inherits from XmlObjectSerializer to call JsonReaderWriterFactory.CreateJsonReader() to create an XmlReader that actually reads JSON, then skip forward to the first nested "element":

protected T DeserializeNestedJsonStringWithReader<T>(string jsonString)
{
    var reader = JsonReaderWriterFactory.CreateJsonReader(Encoding.Unicode.GetBytes(jsonString), System.Xml.XmlDictionaryReaderQuotas.Max);
    int elementCount = 0;

    while (reader.Read())
    {
        if (reader.NodeType == System.Xml.XmlNodeType.Element)
            elementCount++;
        if (elementCount == 2) // At elementCount == 1 there is a synthetic "root" element
        {
            var serializer = new DataContractJsonSerializer(typeof(T));
            return (T)serializer.ReadObject(reader, false);
        }
    }
    return default(T);
}

这种技术看起来很奇怪(使用XmlReader解析JSON?),但是通过一些额外的工作,应该可以扩展这种想法以创建

This technique looks odd (parsing JSON with an XmlReader?), but with some extra work it should be possible to extend this idea to create SAX-like parsing functionality for JSON that is similar to SelectToken(), skipping forward in the JSON until a desired property is found, then deserializing its value.

例如,要选择和反序列化特定的命名属性,而不仅仅是第一个根属性,可以使用以下内容:

For instance, to select and deserialize specific named properties, rather than just the first root property, the following can be used:

public static class DataContractJsonSerializerExtensions
{
    public static T DeserializeNestedJsonProperty<T>(string jsonString, string rootPropertyName)
    {
        // Check for count == 2 because there is a synthetic <root> element at the top.
        Predicate<Stack<string>> match = s => s.Count == 2 && s.Peek() == rootPropertyName;
        return DeserializeNestedJsonProperties<T>(jsonString, match).FirstOrDefault();
    }

    public static IEnumerable<T> DeserializeNestedJsonProperties<T>(string jsonString, Predicate<Stack<string>> match)
    {
        DataContractJsonSerializer serializer = null;
        using (var reader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(jsonString), XmlDictionaryReaderQuotas.Max))
        {
            var stack = new Stack<string>();
            while (reader.Read())
            {
                if (reader.NodeType == System.Xml.XmlNodeType.Element)
                {
                    stack.Push(reader.Name);
                    if (match(stack))
                    {
                        serializer = serializer ?? new DataContractJsonSerializer(typeof(T));
                        yield return (T)serializer.ReadObject(reader, false);
                    }
                    if (reader.IsEmptyElement)
                        stack.Pop();
                }
                else if (reader.NodeType == XmlNodeType.EndElement)
                {
                    stack.Pop();
                }
            }
        }
    }
}

请参见在JSON和XML之间进行映射,以详细了解 JsonReaderWriterFactory 将JSON映射到XML. /p>

See Mapping Between JSON and XML for details on how JsonReaderWriterFactory maps JSON to XML.

这篇关于.NET中的JObject.SelectToken等效项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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