Aparentemente, IDictionary<string,object>
se serializa como una matriz de objetos KeyValuePair
(por ejemplo, [{Key:"foo", Value:"bar"}, ...]
). ¿Es posible serializarlo como un objeto en su lugar (por ejemplo, {foo:"bar"}
)?Serializar diccionarios con JavaScriptSerializer
Respuesta
Aunque estoy de acuerdo que JavaScriptSerializer es una porquería y Json.Net es una mejor opción , hay una manera en la que puede hacer que JavaScriptSerializer serialice de la manera que desee. Usted tendrá que registrar un convertidor y reemplazar el método Serialize usar algo como esto:
public class KeyValuePairJsonConverter : JavaScriptConverter
{
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
var instance = Activator.CreateInstance(type);
foreach (var p in instance.GetType().GetPublicProperties())
{
instance.GetType().GetProperty(p.Name).SetValue(instance, dictionary[p.Name], null);
dictionary.Remove(p.Name);
}
foreach (var item in dictionary)
(instance).Add(item.Key, item.Value);
return instance;
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
var result = new Dictionary<string, object>();
var dictionary = obj as IDictionary<string, object>;
foreach (var item in dictionary)
result.Add(item.Key, item.Value);
return result;
}
public override IEnumerable<Type> SupportedTypes
{
get
{
return new ReadOnlyCollection<Type>(new Type[] { typeof(your_type) });
}
}
}
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
javaScriptSerializer.RegisterConverters(new JavaScriptConverter[] { new ExpandoJsonConverter() });
jsonOfTest = javaScriptSerializer.Serialize(test);
// {"x":"xvalue","y":"\/Date(1314108923000)\/"}
Espero que esto ayude!
Estoy tratando de usar su clase, pero parece que su variable 'instance' de' Class Object' no tiene ningún método de agregar. –
No, no es posible con JavaScriptSerializer. Es posible con Json.NET:
public class Bar
{
public Bar()
{
Foos = new Dictionary<string, string>
{
{ "foo", "bar" }
};
}
public Dictionary<string, string> Foos { get; set; }
}
y luego:
var bar = new Bar();
string json = JsonConvert.SerializeObject(bar, new KeyValuePairConverter());
produciría la deseada:
{"Foos":{"foo":"bar"}}
Al principio iba por esa ruta. Ver mi pregunta anterior: http://stackoverflow.com/questions/6416017/json-net-deserializing-nested-dictionaries. Tuve un problema al deserializar diccionarios anidados con Json.NET. – Daniel
@Daniel, Json.NET es azúcar en comparación con 'JavaScriptSerializer'. Entonces, si tiene problemas con Json.NET, no sé qué decir sobre la alternativa :-) En lo que respecta a su otra pregunta, ese es un comportamiento perfectamente normal. Todo lo que indicó al serializador es un diccionario de cadena y objeto. Entonces, estás trabajando con diccionarios de tipo débil en tu código, ¿qué esperas a cambio? Todo lo que puedes obtener es, por supuesto, JObjects de tipeo débil. Use un diccionario fuertemente tipado: 'Dictionary
¿A qué se refiere? No lo estoy viendo – Daniel
Pude resolverlo usando JavaScriptSerializer, el truco es crear su propio convertidor. El siguiente código es el código de trabajo:
public class KeyValuePairJsonConverter : JavaScriptConverter {
public override object Deserialize(IDictionary<string, object> dictionary
, Type type
, JavaScriptSerializer serializer) {
throw new InvalidOperationException("Sorry, I do serializations only.");
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) {
Dictionary<string, object> result = new Dictionary<string, object>();
Dictionary<string, MyClass> dictionaryInput = obj as Dictionary<string, MyClass>;
if (dictionaryInput == null) {
throw new InvalidOperationException("Object must be of Dictionary<string, MyClass> type.");
}
foreach (KeyValuePair<string, MyClass> pair in dictionaryInput)
result.Add(pair.Key, pair.Value);
return result;
}
public override IEnumerable<Type> SupportedTypes {
get {
return new ReadOnlyCollection<Type>(new Type[] { typeof(Dictionary<string, MyClass>) });
}
}
}
Y aquí es cómo lo usa:
JavaScriptSerializer js = new JavaScriptSerializer();
js.RegisterConverters(new JavaScriptConverter[] { new KeyValuePairJsonConverter() });
Context.Response.Clear();
Context.Response.ContentType = "application/json";
Context.Response.Write(js.Serialize(myObject));
He aquí un Creo versión mejorada de la respuesta Tomas. Funciona de maravilla. También podríamos agregar un cheque para el atributo ScriptIgnore pero bueno, noquearlo.
BTW, elegí JavaScriptSerializer porque en mi opinión las soluciones de terceros son la mayoría del tiempo: menos conocidas, largas de instalar, a menudo olvidadas prerrequisitos y con borrosos estados de copia que hacen que sea riesgoso distribuirlas en los negocios.
P-S: No entendía por qué intentábamos deserializar tanto la instancia como la instancia como un diccionario, así que desgasté esa parte.
public class KeyValuePairJsonConverter : JavaScriptConverter
{
public override object Deserialize(IDictionary<string, object> deserializedJSObjectDictionary, Type targetType, JavaScriptSerializer javaScriptSerializer)
{
Object targetTypeInstance = Activator.CreateInstance(targetType);
FieldInfo[] targetTypeFields = targetType.GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo fieldInfo in targetTypeFields)
fieldInfo.SetValue(targetTypeInstance, deserializedJSObjectDictionary[fieldInfo.Name]);
return targetTypeInstance;
}
public override IDictionary<string, object> Serialize(Object objectToSerialize, JavaScriptSerializer javaScriptSerializer)
{
IDictionary<string, object> serializedObjectDictionary = new Dictionary<string, object>();
FieldInfo[] objectToSerializeTypeFields = objectToSerialize.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo fieldInfo in objectToSerializeTypeFields)
serializedObjectDictionary.Add(fieldInfo.Name, fieldInfo.GetValue(objectToSerialize));
return serializedObjectDictionary;
}
public override IEnumerable<Type> SupportedTypes
{
get
{
return new ReadOnlyCollection<Type>(new Type[] { typeof(YOURCLASSNAME) });
}
}
}
Respecto a mi nota de PS. Quizás esto fue para permitir especificar un tipo de diccionario genérico en lugar de un tipo, pero honestamente no veo el punto de especificar un tipo de diccionario genérico, ya que todo esto se trata de deserializar los diccionarios
que era capaz de resolver con JavaScriptSerializer con LINQ Seleccionar:
var dictionary = new Dictionary<int, string>();
var jsonOutput = new JavaScriptSerializer().Serialize(dictionary.Select(x => new { Id = x.Key, DisplayText = x.Value }));
Esto no funciona en casos complejos (es decir, estructuras jerárquicas complejas), pero seguro resuelve el problema en el caso simple, por lo que es una solución a considerar si desea evitar agregar texto estándar a JavaScriptSerializer o una biblioteca de terceros. –
Para mí funcionó incluso en casos complejos, simplemente cambiando a '.Serialize (dictionary)'. Es más simple que JsonConvert, listo para usar. Ojalá pudiera dar +2 a esta respuesta –
- 1. ¿Alguna manera de hacer DataContractJsonSerializer serializar diccionarios correctamente?
- 2. JavaScriptSerializer con tipo personalizado
- 3. ¿Cómo establecer el formato con JavaScriptSerializer cuando se serializa JSON?
- 4. ¿Puede JavaScriptSerializer excluir propiedades con valores nulos/predeterminados?
- 5. XmlAttribute/XmlElement equivalent for JavaScriptSerializer
- 6. Escapar citas con JavaScriptSerializer en ASP.NET MVC3
- 7. Diccionarios diccionarios
- 8. Generics/JSON JavaScriptSerializer C#
- 9. Trabajar con diccionarios inmutables
- 10. JSON.NET JsonConvert vs .NET JavaScriptSerializer
- 11. JSON Serializar Django modelos con simplejson
- 12. Uso de Lambda con diccionarios
- 13. Mapeo de diccionarios con AutoMapper
- 14. Combinar dos diccionarios con LINQ
- 15. Serializar objeto con outputtream
- 16. ¿Cómo serializar ExpandoObject usando ServiceStack JsonSerializer?
- 17. Diccionarios Concatenación
- 18. JSON serializar un objeto con parámetros de la función
- 19. Serializar XNA rectángulo con Json.NET
- 20. ¿Cómo serializar objetos anónimos a XML?
- 21. ¿Cómo deserializar json con diccionarios anidados?
- 22. Arreglo de filtro con diccionarios usando NSPredicate
- 23. Análisis de mapas JSON/diccionarios con Gson?
- 24. Serializar
- 25. serializar Lista/deserializar <T> a JSON
- 26. ¿Comprende la lista Python para diccionarios en los diccionarios?
- 27. C# Merging 2 diccionarios
- 28. C# a Java - ¿Diccionarios?
- 29. Diccionarios y divertido Lambdas
- 30. C# diccionarios intersectar
sí, no haga uso JavaScriptSerializer, su basura por completo. Use Newtonsoft Json.NET –