Cómo analizar el tipo de diccionario con json-ajax
Frecuentes
Visto 14,215 veces
1
Tengo un diccionario que regresará del servidor, lo convertí al formato de cadena json como se muestra a continuación:
public static class Extensions
{
public static string ToJson<T>(this T obj)
{
MemoryStream stream = new MemoryStream();
try {
DataContractJsonSerializer jsSerializer = new DataContractJsonSerializer(typeof(T));
jsSerializer.WriteObject(stream, obj);
return Encoding.UTF8.GetString(stream.ToArray());
}
finally
{
stream.Close();
stream.Dispose();
}
}
public static T FromJson<T>(this string input)
{
MemoryStream stream = new MemoryStream();
try {
DataContractJsonSerializer jsSerializer = new DataContractJsonSerializer(typeof(T));
stream = new MemoryStream(Encoding.UTF8.GetBytes(input));
T obj = (T)jsSerializer.ReadObject(stream); return obj;
}
finally
{
stream.Close();
stream.Dispose();
}
}
}
[WebMethod]
public string callme()
{
Dictionary<int, string> myObjects = new Dictionary<int, string>();
myObjects.Add(1, "This");
myObjects.Add(2, "is");
myObjects.Add(3, "cool");
string json = myObjects.ToJson();
return json;
}
entonces el resultado es:
{"d":"[{\"Key\":1,\"Value\":\"This\"},{\"Key\":2,\"Value\":\"is\"},{\"Key\":3,\"Value\":\"cool\"}]"}
¿Cómo analizo eso en jquery? Estoy intentando esto pero no ayuda
$.ajax({
type: "POST",
url: "web.asmx/callme",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg){
$.each(msg.d, function (i) {
$("#data2").append(i.Key + " " + i.Value + "<br/>");
});
}
});
4 Respuestas
3
Tendrás que hacer esto antes de que funcione:
- Poner un
ScriptService
atribuir a su servicio web - Poner un
ScriptMethod
atributo en su servicio web
Si lo hace, ni siquiera necesita analizar y crear el JSON en el servidor usted mismo. La infraestructura de WS lo hará por usted.
Luego, simplemente use msg.d en el sitio del cliente. Se deserializará automáticamente de la cadena JSOn.
Mire aquí Uso de jQuery para consumir servicios web ASP.NET JSON para lo que necesita hacer en el lado del cliente.
Aquí tiene una muestra de trabajo completa con el lado del cliente y del servidor.
Tenga en cuenta que antes de ASP.NET 3.5, el mensaje de respuesta traía los datos directamente. En 3.5 y posteriores, los datos están en la propiedad .d del mensaje.
EDIT2: forma más fácil de hacerlo Cometí un error en la primera edición: .asmx no puede serializar un Dictionay como XML. Entonces, cuando probé la solución en la primera edición a través de la página .asmx, recibí un error. Pero JSON puede serializar un diccionario que tenga una cadena o un objeto como clave.
Entonces, puedes usar esta clase para convertir tu Dictionary<int,string>
a Dictionary<string,string>
usando esta clase genérica:
public class DictionaryConverter
{
public static Dictionary<string,TValue>
ConvertDictionary<TKey,TValue>(Dictionary<TKey,TValue> dict)
{
Dictionary<string,TValue> newDict
= new Dictionary<string, TValue>();
foreach(TKey key in dict.Keys)
{
newDict.Add(key.ToString(), dict[key]);
}
return newDict;
}
}
Esta clase puede convertir cualquier diccionario con cualquier tipo de clave en un Dictionary<string,Tvalue>
diccionario, que se puede serializar como JSON, pero no como XML. Utiliza el tipo de clave toString()
método para convertir la clave en cadena. Esto funcionará perfectamente para int
y muchos otros tipos. Este método podría extenderse para recibir un delegado para convertir la clave en una cadena si es necesario.
En el lado del cliente, obtienes lo mismo con esta solución y la de la primera edición. La ventaja de la primera edición es que también puede admitir la serialización en XML: puede invocar el método a través de la página .asmx y usar WebMethod como un WebMethod XML regular.
EDITAR: Diccionario de serialización <> en el servicio web .asmx:
El serializador utilizado con asmx no admite la serialización de diccionarios. para XML. Puede crear una clase personalizada y convertir su diccionario en una lista de esta clase personalizada, que tiene una clave y una propiedad de valor (el serializador no admite la serialización KeyValuePair
or Tuple
, tampoco, por lo que debe usar su propia clase).
Esta clase tiene dos propósitos:
- Es una clase que se puede serializar con el serializador que usa asmx para JSON
Permite convertir un diccionario en una lista de elementos de la clase
public class KeyValue<TKey, TValue> { public KeyValue() { } public TKey Key { get; set; } public TValue Value { get; set; } public static List<KeyValue<TKey,TValue>> ConvertDictionary (Dictionary<TKey,TValue> dictionary) { List<KeyValue<TKey, TValue>> newList = new List<KeyValue<TKey, TValue>>(); foreach (TKey key in dictionary.Keys) { newList.Add(new KeyValue<TKey, TValue> { Key = key, Value = dictionary[key] }); } return newList; } }
Su método web debería verse así:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)] // it's JSON by default
public List<KeyValue<int,string>> GetKeyValueList()
{
List<KeyValue<int, string>> list
= KeyValue<int,string>.ConvertDictionary(yourDictionary);
return list;
}
Notas
- puede usar cualquier nombre de método en lugar de
GetKeyValueList
- la TKey, TValue debe ser del mismo tipo que la clave y el valor de su diccionario.
En el lado del cliente, obtiene una matriz de Objetos con propiedades Clave y Valor, a los que se puede acceder de esta manera:
msg.d[0].Key
msg.d[0].Value
Esta es la llamada jquery ajax:
$(document).ready(function () {
$.ajax({
url: 'MyService.asmx/GetKeyValueList',
type: "POST",
data: "{}",
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (msg) {
// use msg.d array of objects with Key and Value
}
});
});
contestado el 05 de mayo de 12 a las 04:05
2
$.each(msg.d, function() {
$("#data2").append(this.Key + " " + this.Value + "<br/>");
});
Además, parece que su serialización no funciona correctamente, ya que la respuesta que regresa no se analiza por completo en JSON. Los contenidos de d
no debería ser una cadena, debería ser un objeto/matriz.
contestado el 03 de mayo de 12 a las 15:05
Puedes hacer console.log(msg)
y poner la respuesta de eso aquí? - Eli
jajaja. el último: Object { d="[{"Key":1,"Value":"This...Key":3,"Value":"cool"}]"} - Mustafa Ekici
Qué tal esto: console.log( typeof msg.d );
- Eli
Parece que su serialización no funciona correctamente, ya que la respuesta que regresa no se analiza por completo en JSON. Los contenidos de d
no debería ser una cadena, debería ser un objeto/matriz. - Eli
usé el diccionario sin convertir la cadena jsong, por lo que msg.d regresa como objeto/matriz para que su respuesta no funcione. ¿qué piensas? - Mustafa Ekici
1
Basado en la respuesta anterior de JotaBe, creé este método de extensión:
public class KeyValue<TKey, TValue>
{
public TKey Key { get; set; }
public TValue Value { get; set; }
public KeyValue()
{
}
}
public static class KeyValue_extensionMethods
{
public static List<KeyValue<TKey, TValue>> ConvertDictionary<TKey, TValue>(this Dictionary<TKey, TValue> dictionary)
{
var keyValueList = new List<KeyValue<TKey, TValue>>();
foreach (TKey key in dictionary.Keys)
keyValueList.Add(new KeyValue<TKey, TValue> { Key = key, Value = dictionary[key] });
return keyValueList;
}
}
Lo que luego me permite consumirlo usando {objeto}.ConvertDictionary() sintaxis. Por ejemplo:
[WebMethod(EnableSession = true)] [Admin(SecurityAction.Demand)]
public List<KeyValue<Guid, string>> Data_GuidanceItems_FileMappings()
{
return TM_Xml_Database.GuidanceItems_FileMappings.ConvertDictionary();
}
Respondido el 16 de Septiembre de 12 a las 12:09
1
La única forma en que funcionó para mí fue
var $nomeP = $("#<%= tbxBuscaJornalista.ClientID %>").val();
$.ajax({
url: "MyPage.asmx/MyMethod",
dataType: "json",
type: "POST",
data: "{ 'variableName': '"+$nomeP+"' }",
contentType: "application/json; charset=utf-8",
success: function (msg) {
$.each(msg.d, function (index, value) {
$("#somePanel").append(index + " " + value + "<br/>");
});
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("Error: " + errorThrown + " XmlRequest: " + XMLHttpRequest);
}
});
Por favor, observe la línea data: "{ 'variableName': '"+$nomeP+"' }"
lo que demuestra que tuve que encierre el nombre de la variable (igual que se esperaba en el código subyacente) y el valor entre comillas simples. De lo contrario, no funcionaría. Además, traté de iterar y usar $(this).Key
y $(this).Value
pero eso tampoco funcionaría. Me vi obligado a usar el function (index, value)
enfoque.
Respondido el 05 de junio de 14 a las 20:06
Luego, simplemente use msg.d en el sitio del cliente. Se deserializará automáticamente de la cadena JSOn. Entonces, ¿cómo en mi json? - Mustafa Ekici
Mire la muestra en "muestra de trabajo completa". Cambia los datos devueltos por el método web por un diccionario y verás que el
.d
La propiedad de la respuesta se puede usar directamente en el lado del cliente sin deserializarla. - JotaBehmm bien, gracias, de hecho, mi pregunta era de 2 partes, una de la solución proviene de usted y la otra de eli;) - Mustafa Ekici
@mekici: JotaBe mencionó esto, pero el quid de su problema es que está serializando manualmente el JSON en su método de servicio. Dado que ASP.NET lo hace automáticamente en este caso, terminará con datos doblemente serializados. Tengo una publicación dedicada a ese problema específico aquí: encosia.com/… - Dave Ward
Echa un vistazo a mi respuesta editada. @DaveWard a partir de .NET 4.0, el servicio asmx no puede realizar la serialización JSON de Dictionary, incluso si es . - JotaBe