/// /// Converts an ExpandoObject to and from JSON, handling object references. /// public class ObjectReferenceExpandoObjectConverter : JsonConverter { // Adapted from https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { // can write is set to false throw new NotImplementedException(); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { return ReadValue(serializer, reader); } private object ReadValue(JsonSerializer serializer, JsonReader reader) { while (reader.TokenType == JsonToken.Comment) { if (!reader.Read()) throw reader.CreateException("Unexpected end when reading ExpandoObject."); } switch (reader.TokenType) { case JsonToken.StartObject: return ReadObject(serializer, reader); case JsonToken.StartArray: return ReadList(serializer, reader); default: if (JsonTokenUtils.IsPrimitiveToken(reader.TokenType)) return reader.Value; throw reader.CreateException("Unexpected token when converting ExpandoObject"); } } private object ReadList(JsonSerializer serializer, JsonReader reader) { IList
然后使用它像:
var settings = new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects, ReferenceLoopHandling = ReferenceLoopHandling.Serialize }; settings.Converters.Add(new ObjectReferenceExpandoObjectConverter()); dynamic d = JsonConvert.DeserializeObject(json, settings);
我现在的方式是使用后处理步骤和递归函数,它正在执行自己的引用保存和重新布线:
private static void Reffing(this IDictionary current, Action exchange,IDictionary refdic) { object value; if(current.TryGetValue("$ref", out value)) { if(!refdic.TryGetValue((string) value, out value)) throw new Exception("ref not found "); if (exchange != null) exchange(value); return; } if (current.TryGetValue("$id", out value)) { refdic[(string) value] = current; } foreach (var kvp in current.ToList()) { if (kvp.Key.StartsWith("$")) continue; var expandoObject = kvp.Value as ExpandoObject; if(expandoObject != null) Reffing(expandoObject,o => current[kvp.Key]=o,refdic); var list = kvp.Value as IList; if (list == null) continue; for (var i = 0; i < list.Count; i++) { var lEO = list[i] as ExpandoObject; if(lEO!=null) Reffing(lEO,o => list[i]=o,refdic); } } }
用作:
var test = JsonConvert.DeserializeObject(...); var dictionary = new Dictionary(); Reffing(test,null,dictionary);