don*_*hon 42 .net json json.net deserialization
我需要将复杂的JSON blob反序列化为标准的.NET容器,以便在不了解JSON的代码中使用.它期望的事情是在标准的.NET类型,具体地Dictionary<string, object>或List<object>其中"对象"可以是原语或递归(词典或列表).
我不能使用静态类型来映射结果,并且JObject/JToken不适合.理想情况下,有一些方法(通过Contracts可能?)将原始JSON转换为基本的.NET容器.
我一直在寻找任何方式来哄骗JSON.NET反序列化器在遇到"{}"或"[]"时创建这些简单类型,但收效甚微.
任何帮助赞赏!
Bri*_*ers 58
如果您只想要一个可以处理任意JSON并将其转换为常规.NET类型(基元,列表和字典)的嵌套结构的泛型方法,则可以使用JSON.Net的LINQ-to-JSON API来执行此操作:
using System.Linq;
using Newtonsoft.Json.Linq;
public static class JsonHelper
{
public static object Deserialize(string json)
{
return ToObject(JToken.Parse(json));
}
private static object ToObject(JToken token)
{
switch (token.Type)
{
case JTokenType.Object:
return token.Children<JProperty>()
.ToDictionary(prop => prop.Name,
prop => ToObject(prop.Value));
case JTokenType.Array:
return token.Select(ToObject).ToList();
default:
return ((JValue)token).Value;
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以调用如下所示的方法. obj将包含a Dictionary<string, object>,List<object>或原语,具体取决于您开始使用的JSON.
object obj = JsonHelper.Deserialize(jsonString);
Run Code Online (Sandbox Code Playgroud)
Ani*_*tel 13
使用JSON.NET以递归方式将json字符串反序列化为字典和列表的一种方法是创建一个自定义json转换器类,该类派生自JsonConverterJSON.NET提供的抽象类.
在你的派生中JsonConverter,你将如何写入和从json写入对象的实现.
您可以JsonConverter像这样使用自定义:
var o = JsonConvert.DeserializeObject<IDictionary<string, object>>(json, new DictionaryConverter());
Run Code Online (Sandbox Code Playgroud)
这是我过去成功使用的自定义JsonConverter,用于实现与您在问题中概述的目标相同的目标:
public class DictionaryConverter : JsonConverter {
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { this.WriteValue(writer, value); }
private void WriteValue(JsonWriter writer, object value) {
var t = JToken.FromObject(value);
switch (t.Type) {
case JTokenType.Object:
this.WriteObject(writer, value);
break;
case JTokenType.Array:
this.WriteArray(writer, value);
break;
default:
writer.WriteValue(value);
break;
}
}
private void WriteObject(JsonWriter writer, object value) {
writer.WriteStartObject();
var obj = value as IDictionary<string, object>;
foreach (var kvp in obj) {
writer.WritePropertyName(kvp.Key);
this.WriteValue(writer, kvp.Value);
}
writer.WriteEndObject();
}
private void WriteArray(JsonWriter writer, object value) {
writer.WriteStartArray();
var array = value as IEnumerable<object>;
foreach (var o in array) {
this.WriteValue(writer, o);
}
writer.WriteEndArray();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
return ReadValue(reader);
}
private object ReadValue(JsonReader reader) {
while (reader.TokenType == JsonToken.Comment) {
if (!reader.Read()) throw new JsonSerializationException("Unexpected Token when converting IDictionary<string, object>");
}
switch (reader.TokenType) {
case JsonToken.StartObject:
return ReadObject(reader);
case JsonToken.StartArray:
return this.ReadArray(reader);
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 reader.Value;
default:
throw new JsonSerializationException
(string.Format("Unexpected token when converting IDictionary<string, object>: {0}", reader.TokenType));
}
}
private object ReadArray(JsonReader reader) {
IList<object> list = new List<object>();
while (reader.Read()) {
switch (reader.TokenType) {
case JsonToken.Comment:
break;
default:
var v = ReadValue(reader);
list.Add(v);
break;
case JsonToken.EndArray:
return list;
}
}
throw new JsonSerializationException("Unexpected end when reading IDictionary<string, object>");
}
private object ReadObject(JsonReader reader) {
var obj = new Dictionary<string, object>();
while (reader.Read()) {
switch (reader.TokenType) {
case JsonToken.PropertyName:
var propertyName = reader.Value.ToString();
if (!reader.Read()) {
throw new JsonSerializationException("Unexpected end when reading IDictionary<string, object>");
}
var v = ReadValue(reader);
obj[propertyName] = v;
break;
case JsonToken.Comment:
break;
case JsonToken.EndObject:
return obj;
}
}
throw new JsonSerializationException("Unexpected end when reading IDictionary<string, object>");
}
public override bool CanConvert(Type objectType) { return typeof(IDictionary<string, object>).IsAssignableFrom(objectType); }
}
Run Code Online (Sandbox Code Playgroud)
这是相当于f#:
type IDictionaryConverter() =
inherit JsonConverter()
let rec writeValue (writer: JsonWriter) (value: obj) =
let t = JToken.FromObject(value)
match t.Type with
| JTokenType.Object -> writeObject writer value
| JTokenType.Array -> writeArray writer value
| _ -> writer.WriteValue value
and writeObject (writer: JsonWriter) (value: obj) =
writer.WriteStartObject ()
let obj = value :?> IDictionary<string, obj>
for kvp in obj do
writer.WritePropertyName kvp.Key
writeValue writer kvp.Value
writer.WriteEndObject ()
and writeArray (writer: JsonWriter) (value: obj) =
writer.WriteStartArray ()
let array = value :?> IEnumerable<obj>
for o in array do
writeValue writer o
writer.WriteEndArray ()
let rec readValue (reader: JsonReader) =
while reader.TokenType = JsonToken.Comment do
if reader.Read () |> not then raise (JsonSerializationException("Unexpected token when reading object"))
match reader.TokenType with
| JsonToken.Integer
| JsonToken.Float
| JsonToken.String
| JsonToken.Boolean
| JsonToken.Undefined
| JsonToken.Null
| JsonToken.Date
| JsonToken.Bytes -> reader.Value
| JsonToken.StartObject -> readObject reader Map.empty
| JsonToken.StartArray -> readArray reader []
| _ -> raise (JsonSerializationException(sprintf "Unexpected token when reading object: %O" reader.TokenType))
and readObject (reader: JsonReader) (obj: Map<string, obj>) =
match reader.Read() with
| false -> raise (JsonSerializationException("Unexpected end when reading object"))
| _ -> reader.TokenType |> function
| JsonToken.Comment -> readObject reader obj
| JsonToken.PropertyName ->
let propertyName = reader.Value.ToString ()
if reader.Read() |> not then raise (JsonSerializationException("Unexpected end when reading object"))
let value = readValue reader
readObject reader (obj.Add(propertyName, value))
| JsonToken.EndObject -> box obj
| _ -> raise (JsonSerializationException(sprintf "Unexpected token when reading object: %O" reader.TokenType))
and readArray (reader: JsonReader) (collection: obj list) =
match reader.Read() with
| false -> raise (JsonSerializationException("Unexpected end when reading array"))
| _ -> reader.TokenType |> function
| JsonToken.Comment -> readArray reader collection
| JsonToken.EndArray -> box collection
| _ -> collection @ [readValue reader] |> readArray reader
override __.CanConvert t = (typeof<IDictionary<string, obj>>).IsAssignableFrom t
override __.WriteJson (writer:JsonWriter, value: obj, _:JsonSerializer) = writeValue writer value
override __.ReadJson (reader:JsonReader, _: Type, _:obj, _:JsonSerializer) = readValue reader
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
24492 次 |
| 最近记录: |