我需要删除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
。但是,如果您只是想打开外部根节点,而事先不知道节点名称,则可以使用以下选项。
-
如果使用.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>
以获得第一个属性,因为此类中项目的顺序未定义。 -
在任何支持数据协定序列化程序的.Net版本上,您都可以利用
DataContractJsonSerializer
从XmlObjectSerializer
继承的事实来调用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之间的映射。