これらすべての答えは、大きなオブジェクトからその小さな文字列を取得できると想定しているようです...マッピング内のどこかにそのようなディクショナリで単純に大きなオブジェクトを非現実化することを望んでいる人、およびSystem.Runtime.Serialization.Json
DataContractシステムを使用している人のために、ここにあります解決策:
gis.stackexchange.comへの回答には、この興味深いリンクがありました。私はarchive.orgでそれを回復する必要がありましたが、それはかなり完璧な解決策を提供します:IDataContractSurrogate
あなたが正確にあなた自身の型を実装するカスタムクラスです。簡単に拡張できました。
でも、たくさんの変更を加えました。元のソースが利用できなくなったため、クラス全体をここに投稿します。
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
}
}
新しいサポートされている型をクラスに追加するには、クラスを追加し、それに適切なコンストラクターと関数を与え(SurrogateDictionary
例を参照)、クラスがを継承していることを確認しJsonSurrogateObject
、型マッピングをKnownTypes
ディクショナリに追加するだけです。含まれているSurrogateDictionaryはDictionary<String,T>
、Tが正しく逆シリアル化される任意の型である任意の型の基礎として機能します。
それを呼び出すことは本当に簡単です:
MyObjtype newObj = JsonSurrogate.Deserialize<MyObjtype>(jsonStr, encoding);
なんらかの理由で、これにはスペースを含むキー文字列の使用に問題があることに注意してください。それらは単に最終的なリストに含まれていませんでした。単にjsonの仕様に反していて、私が呼んでいたapiの実装が不十分だったかもしれません。私は知らないよ。とにかく、生のjsonデータでアンダースコアをregexに置き換え、逆シリアル化後に辞書を修正することで、これを解決しました。
JavaScriptSerizlizer
ASP.NET MVCで使用され、廃止されなくなりました。