.NET中的JObject.SelectToken等效项 [英] JObject.SelectToken Equivalent in .NET
问题描述
我需要删除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.
If you are using .Net 4.5 or later, you can deserialize to a
Dictionary<string, T>
withDataContractJsonSerializer.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
继承自 JsonReaderWriterFactory.CreateJsonReader()
创建一个实际上读取JSON的XmlReader
,然后跳到第一个嵌套的元素":>
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屋!