Najwyraźniej IDictionary<string,object>
jest serializowany jako tablica obiektów KeyValuePair
(np. [{Key:"foo", Value:"bar"}, ...]
). Czy istnieje możliwość serializacji jako obiektu (np. {foo:"bar"}
)?Serializowanie słowników z JavaScriptSerializer
Odpowiedz
Chociaż zgadzam się, że to bzdura JavaScriptSerializer i Json.Net jest lepszym rozwiązaniem , jest sposób, w jaki można przekształcić JavaScriptSerializer serializując tak, jak chcesz. Będziesz musiał zarejestrować konwertera i zastąpić metodę serializacji użyciu coś takiego:
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)\/"}
Nadzieja to pomaga!
Próbuję użyć twojej klasy, ale wygląda na to, że twoja zmienna 'instance' z' Class Object' nie ma metody dodawania. –
Nie, nie jest to możliwe z JavaScriptSerializer. Jest to możliwe z Json.NET:
public class Bar
{
public Bar()
{
Foos = new Dictionary<string, string>
{
{ "foo", "bar" }
};
}
public Dictionary<string, string> Foos { get; set; }
}
, a następnie:
var bar = new Bar();
string json = JsonConvert.SerializeObject(bar, new KeyValuePairConverter());
przyniosłoby pożądany:
{"Foos":{"foo":"bar"}}
Najpierw jechałem tą trasą. Zobacz moje poprzednie pytanie: http://stackoverflow.com/questions/6416017/json-net-deserializing-nested-dictionaries. Miałem problem z deserializacją zagnieżdżonych słowników z Json.NET. – Daniel
@ Daniel, Json.NET to cukier w porównaniu do 'JavaScriptSerializer'. Więc jeśli masz problemy z Json.NET, nie wiem, co powiedzieć na temat alternatywy :-) Jeśli chodzi o twoje inne pytanie, jest to całkowicie normalne zachowanie. Wszystko, co wskazałeś na serializer, to słownik łańcucha i obiektu. Pracujesz więc ze słabo wpisanymi słownikami w swoim kodzie, czego oczekujesz w zamian? Jedyne, co można uzyskać, to oczywiście JObjects o słabym typie. Użyj mocno napisanego słownika: 'Dictionary
Na jaką różnicę się powołujesz? Nie widzę tego. – Daniel
Udało mi się go rozwiązać za pomocą JavaScriptSerializer, a sztuczka polega na stworzeniu własnego konwertera. Poniższy kod jest kod działa:
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>) });
}
}
}
A oto jak go używać:
JavaScriptSerializer js = new JavaScriptSerializer();
js.RegisterConverters(new JavaScriptConverter[] { new KeyValuePairJsonConverter() });
Context.Response.Clear();
Context.Response.ContentType = "application/json";
Context.Response.Write(js.Serialize(myObject));
Oto wierzę ulepszoną wersję z Tomasem odpowiedź. Działa jak marzenie. Moglibyśmy również dodać atrybut ScriptIgnore, ale dobrze, znokautujcie.
BTW, wybrałem JavaScriptSerializer, ponieważ moim zdaniem rozwiązania firm trzecich są w większości przypadków: mniej znane, długie instalowanie, często zapomniane żądania wstępne i rozmycie - prawo - które stwarzają ryzyko dla dystrybucji w biznesie.
P-S: Nie rozumiem, dlaczego próbowaliśmy deserializować zarówno do instancji, jak i do instancji jako słownik, więc usunąłem tę część.
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) });
}
}
}
Odnośnie mojej uwagi PS. Być może miało to pozwolić na określenie typowego słownika, a nie typu, ale szczerze mówiąc nie widzę sensu określania ogólnego rodzaju słownika, ponieważ cała ta sprawa dotyczy deserializacji słowników o nazwie
udało mi się rozwiązać z JavaScriptSerializer z LINQ Select:
var dictionary = new Dictionary<int, string>();
var jsonOutput = new JavaScriptSerializer().Serialize(dictionary.Select(x => new { Id = x.Key, DisplayText = x.Value }));
Nie działa to w złożonych przypadkach (to jest w złożonych strukturach hierarchicznych), ale z pewnością rozwiązuje problem w prostym przypadku, więc jest to rozwiązanie, które należy rozważyć, jeśli nie chcesz dodawać zestawu znaków do JavaScriptSerializer lub biblioteki innej firmy. –
Dla mnie działało to nawet w skomplikowanych przypadkach, po prostu zmieniając na '.Serialize (słownik)'. Jest prostszy niż JsonConvert, gotowy do użycia. Chciałbym dać odpowiedź na tę odpowiedź –
- 1. JavaScriptSerializer z niestandardowym typem
- 2. serializowanie danych przy użyciu limitu rozmiaru json.net?
- 3. Generics/JSON JavaScriptSerializer C#
- 4. JSON.NET JsonConvert vs .NET JavaScriptSerializer
- 5. Json.NET: serializowanie/deserializacja macierzy
- 6. Python: serializowanie/deserializowanie datetime.time
- 7. Odpowiednik XmlAttribute/XmlElement dla JavaScriptSerializer
- 8. Serializowanie tablicy w Jquery?
- 9. Odejmij wartości z listy słowników od innej listy słowników
- 10. serializowanie obiektów do json z play.api.libs.json
- 11. Python. Manipulacja z listą słowników
- 12. Usuwanie wielu słowników z listy
- 13. Pobieranie słowników atrybutów z NSAttributedString
- 14. Serializowanie i odtwarzanie nieznanej klasy
- 15. Serializowanie map zainicjowanych w konstruktorach
- 16. Serializowanie poszarpanej tablicy bajtów wydajnie
- 17. Serializowanie funkcji anonimowych w php
- 18. Czy JavaScriptSerializer może wykluczyć właściwości z wartościami null/default?
- 19. Jak zmusić camelcase za pomocą JavaScriptSerializer?
- 20. C# Scalanie 2 słowników
- 21. Python: Sortowanie słownika słowników
- 22. Słownik python słowników
- 23. Wyciąg wszystkie klucze z listy słowników
- 24. Jak słownika słowników z wielu list
- 25. Usuwanie kluczowych wartości par z listy słowników
- 26. Przechowywanie słowników w Firebase?
- 27. Serializowanie obiektu żądania za pomocą JSON
- 28. Porównanie list słowników
- 29. Zapytanie słownik słowników?
- 30. Powtarzanie słowników VBA?
tak, nie używaj JavaScriptSerializer, jej całkowicie bzdura. Użyj Newtonsoft Json.NET –