Dường như tất cả các câu trả lời ở đây chỉ giả sử bạn có thể lấy chuỗi nhỏ đó ra khỏi một vật thể lớn hơn ... đối với những người muốn đơn giản hóa giải thích một đối tượng lớn với một từ điển như vậy ở đâu đó trong ánh xạ và những người đang sử dụng System.Runtime.Serialization.Json
hệ thống DataContract, đây một giải pháp:
Một câu trả lời trên gis.stackexchange.com đã có liên kết thú vị này . Tôi đã phải khôi phục nó với archive.org, nhưng nó cung cấp một giải pháp khá hoàn hảo: một IDataContractSurrogate
lớp tùy chỉnh trong đó bạn thực hiện chính xác các kiểu của riêng bạn. Tôi đã có thể mở rộng nó một cách dễ dàng.
Tôi đã thực hiện một loạt các thay đổi trong đó, mặc dù. Vì nguồn ban đầu không còn nữa, tôi sẽ đăng toàn bộ lớp ở đây:
using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
namespace JsonTools
{
/// <summary>
/// Allows using Dictionary<String,String> and Dictionary<String,Boolean> types, and any others you'd like to add.
/// Source: https://web.archive.org/web/20100317222656/my6solutions.com/post/2009/06/30/DataContractSerializer-DataContractJsonSerializer-JavaScriptSerializer-XmlSerializer-for-serialization.aspx
/// </summary>
public class JsonSurrogate : IDataContractSurrogate
{
/// <summary>
/// Deserialize an object with added support for the types defined in this class.
/// </summary>
/// <typeparam name="T">Contract class</typeparam>
/// <param name="json">JSON String</param>
/// <param name="encoding">Text encoding</param>
/// <returns>The deserialized object of type T</returns>
public static T Deserialize<T>(String json, Encoding encoding)
{
if (encoding == null)
encoding = new UTF8Encoding(false);
DataContractJsonSerializer deserializer = new DataContractJsonSerializer(
typeof(T), new Type[0], int.MaxValue, true, new JsonSurrogate(), false);
using (MemoryStream stream = new MemoryStream(encoding.GetBytes(json)))
{
T result = (T)deserializer.ReadObject(stream);
return result;
}
}
// make sure all values in this are classes implementing JsonSurrogateObject.
private static Dictionary<Type, Type> KnownTypes =
new Dictionary<Type, Type>()
{
{typeof(Dictionary<String, String>), typeof(SSDictionary)},
{typeof(Dictionary<String, Boolean>), typeof(SBDictionary)}
};
#region Implemented surrogate dictionary classes
[Serializable]
public class SSDictionary : SurrogateDictionary<String>
{
public SSDictionary() : base() {}
protected SSDictionary (SerializationInfo info, StreamingContext context) : base(info, context) {}
}
[Serializable]
public class SBDictionary : SurrogateDictionary<Boolean>
{
public SBDictionary() : base() {}
protected SBDictionary (SerializationInfo info, StreamingContext context) : base(info, context) {}
}
#endregion
/// <summary>Small interface to easily extract the final value from the object.</summary>
public interface JsonSurrogateObject
{
Object DeserializedObject { get; }
}
/// <summary>
/// Class for deserializing any simple dictionary types with a string as key.
/// </summary>
/// <typeparam name="T">Any simple type that will be deserialized correctly.</typeparam>
[Serializable]
public abstract class SurrogateDictionary<T> : ISerializable, JsonSurrogateObject
{
public Object DeserializedObject { get { return dict; } }
private Dictionary<String, T> dict;
public SurrogateDictionary()
{
dict = new Dictionary<String, T>();
}
// deserialize
protected SurrogateDictionary(SerializationInfo info, StreamingContext context)
{
dict = new Dictionary<String, T>();
foreach (SerializationEntry entry in info)
{
// This cast will only work for base types, of course.
dict.Add(entry.Name, (T)entry.Value);
}
}
// serialize
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
foreach (String key in dict.Keys)
{
info.AddValue(key, dict[key]);
}
}
}
/// <summary>
/// Uses the KnownTypes dictionary to get the surrogate classes.
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public Type GetDataContractType(Type type)
{
Type returnType;
if (KnownTypes.TryGetValue(type, out returnType))
{
return returnType;
}
return type;
}
public object GetObjectToSerialize(object obj, Type targetType)
{
throw new NotImplementedException();
}
/// <summary>
/// Gets the object out of the surrogate datacontract object. This function is the reason all surrogate objects need to implement the JsonSurrogateObject class.
/// </summary>
/// <param name="obj">Result of the deserialization</param>
/// <param name="targetType">Expected target type of the deserialization</param>
/// <returns></returns>
public object GetDeserializedObject(object obj, Type targetType)
{
if (obj is JsonSurrogateObject)
{
return ((JsonSurrogateObject)obj).DeserializedObject;
}
return obj;
}
public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
{
return null;
}
#region not implemented
public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType)
{
throw new NotImplementedException();
}
public object GetCustomDataToExport(Type clrType, Type dataContractType)
{
throw new NotImplementedException();
}
public void GetKnownCustomDataTypes(Collection<Type> customDataTypes)
{
throw new NotImplementedException();
}
public CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit)
{
throw new NotImplementedException();
}
#endregion
}
}
Để thêm các loại được hỗ trợ mới vào lớp, bạn chỉ cần thêm lớp của mình, cung cấp cho nó các hàm tạo và hàm đúng (xem SurrogateDictionary
ví dụ), đảm bảo rằng nó kế thừa JsonSurrogateObject
và thêm ánh xạ kiểu của nó vào KnownTypes
từ điển. SurrogateDixi đi kèm có thể dùng làm cơ sở cho bất kỳ Dictionary<String,T>
loại nào trong đó T là bất kỳ loại nào giải nén chính xác.
Gọi nó là rất đơn giản:
MyObjtype newObj = JsonSurrogate.Deserialize<MyObjtype>(jsonStr, encoding);
Lưu ý rằng vì một số lý do, điều này gặp sự cố khi sử dụng các chuỗi khóa có chứa khoảng trắng; họ chỉ đơn giản là không có mặt trong danh sách cuối cùng. Có thể chỉ đơn giản là nó chống lại thông số kỹ thuật của json và api mà tôi đang gọi được thực hiện kém, làm phiền bạn; Tôi không biết. Dù sao, tôi đã giải quyết điều này bằng cách thay thế chúng bằng dấu gạch dưới trong dữ liệu json thô và sửa từ điển sau khi khử lưu huỳnh.
JavaScriptSerizlizer
được sử dụng trong ASP.NET MVC và không còn bị phản đối nữa.