JObject.SelectToken Equivalent in .NET



我需要删除JSON的外部节点。例如:

{
    app: {
       ...
    }
}

关于如何删除外部节点的任何想法,因此我们只能获得

{
   ...
}

WITH使用JSON.NET,仅限.NET Framework(C#)中的工具。

在Json.NET中,我使用了:

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

或者,DataContractJsonSerializer的任何配置,使其在反序列化时忽略根,也可以工作。我现在进行去序列化的方式是:

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"

谢谢你的建议。

.Net中没有等效的SelectToken。但是,如果您只是想打开外部根节点,而事先不知道节点名称,则可以使用以下选项。

  1. 如果使用.Net 4.5或更高版本,则可以使用DataContractJsonSerializer.UseSimpleDictionaryFormat = true:反序列化为Dictionary<string, T>

    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>以获得第一个属性,因为此类中项目的顺序未定义。

  2. 在任何支持数据协定序列化程序的.Net版本上,您都可以利用DataContractJsonSerializerXmlObjectSerializer继承的事实来调用JsonReaderWriterFactory.CreateJsonReader()来创建一个实际读取JSON的XmlReader,然后跳到第一个嵌套的"元素":

    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?),但通过一些额外的工作,应该可以扩展这种想法,为类似于SelectToken()的JSON创建类似SAX的解析功能,在JSON中向前跳过,直到找到所需的属性,然后反序列化其值。

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

    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();
                    }
                }
            }
        }
    }
    

    有关JsonReaderWriterFactory如何将JSON映射到XML的详细信息,请参阅JSON和XML之间的映射。

相关内容

  • 没有找到相关文章

最新更新