Кажется, все эти ответы здесь предполагают, что вы можете получить эту маленькую строку из более крупного объекта ... для людей, которые хотят просто обезвреживать большой объект с помощью такого словаря где-то внутри сопоставления и кто использует System.Runtime.Serialization.Json
DataContract system, вот решение:
Ответ на 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
{
///
/// 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
///
public class JsonSurrogate : IDataContractSurrogate
{
///
/// Deserialize an object with added support for the types defined in this class.
///
/// Contract class
/// JSON String
/// Text encoding
/// The deserialized object of type T
public static T Deserialize(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 KnownTypes =
new Dictionary()
{
{typeof(Dictionary), typeof(SSDictionary)},
{typeof(Dictionary), typeof(SBDictionary)}
};
#region Implemented surrogate dictionary classes
[Serializable]
public class SSDictionary : SurrogateDictionary
{
public SSDictionary() : base() {}
protected SSDictionary (SerializationInfo info, StreamingContext context) : base(info, context) {}
}
[Serializable]
public class SBDictionary : SurrogateDictionary
{
public SBDictionary() : base() {}
protected SBDictionary (SerializationInfo info, StreamingContext context) : base(info, context) {}
}
#endregion
/// Small interface to easily extract the final value from the object.
public interface JsonSurrogateObject
{
Object DeserializedObject { get; }
}
///
/// Class for deserializing any simple dictionary types with a string as key.
///
/// Any simple type that will be deserialized correctly.
[Serializable]
public abstract class SurrogateDictionary : ISerializable, JsonSurrogateObject
{
public Object DeserializedObject { get { return dict; } }
private Dictionary dict;
public SurrogateDictionary()
{
dict = new Dictionary();
}
// deserialize
protected SurrogateDictionary(SerializationInfo info, StreamingContext context)
{
dict = new Dictionary();
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]);
}
}
}
///
/// Uses the KnownTypes dictionary to get the surrogate classes.
///
///
///
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();
}
///
/// Gets the object out of the surrogate datacontract object. This function is the reason all surrogate objects need to implement the JsonSurrogateObject class.
///
/// Result of the deserialization
/// Expected target type of the deserialization
///
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 customDataTypes)
{
throw new NotImplementedException();
}
public CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit)
{
throw new NotImplementedException();
}
#endregion
}
}
Чтобы добавить новые поддерживаемые типы в класс, вам просто нужно добавить свой класс, дать ему правильные конструкторы и функции (посмотрите на SurrogateDictionary
для примера), убедитесь, что он наследует JsonSurrogateObject
и добавляет его сопоставление типов в словарь KnownTypes
. Включенный SurrogateDictionary может служить основой для любых типов Dictionary
, где T - любой тип, который десериализуется правильно.
Вызов очень простой:
MyObjtype newObj = JsonSurrogate.Deserialize(jsonStr, encoding);
Обратите внимание, что для некоторых причина в том, что эта вещь имеет проблемы с использованием ключевых строк, содержащих пробелы; они просто не присутствовали в финальном списке. Может быть, это просто против json specs, и api, который я звонил, был плохо реализован, заметьте; Не знаю. Во всяком случае, я решил это путем регулярного выражения, заменив их символами подчеркивания в исходных данных json и установив словарь после десериализации.
Как априори максимум и минимум не уникальны, вы можете играть из
import pandas as pd
import numpy as np
df = pd.DataFrame(np.arange(6).reshape(2,3))
#show max
df[df==df.max().max()]
#show min
df[df==df.min().min()]