2015-03-12 12 views
6

Używamy Json.net do serializacji. i chcemy umożliwić serializowanie praktycznie każdego rodzaju klasy/komunikatu użytkownika.Zastępcza wartość int, float i decimal za pomocą Json.NET

Jedną rzeczą, która Json.net nie może obsługiwać po wyjęciu z pudełka jest, jeśli przechowywać int, float lub decimal w polu object. np.

public class SomeMessage 
{ 
     public object Something {get;set;} 
} 

gdybym przechowywać int, float lub decimal w dziedzinie coś będzie rozszeregować się albo long lub double (jak json.net nie może nic więcej niż domyślać rodzaju prymitywne zrobić JSON („foo”: 123 < - int lub long).

Im całkowicie świadomy, że mogę użyć właściwego typu na nieruchomości i ustawić różne podpowiedzi

Ale chcę, aby rozwiązać ten problem dla dowolnego losowo klasa/wiadomość:

Moje obecne podejście to niestandardowy JsonConverter, który zajmuje się powyższymi typami, a następnie serializuje je do typu zastępczego, który przechowuje wartość jako łańcuch znaków i dyskryminator dla tego typu. A potem na ReadJson, zmieniam go z powrotem w poprawny typ.

W tym celu występuje zbyt dużo przegrzania. szczególnie w przypadku nazwy typu zastępczego. "foo.bar.baz.PrimitiveSurrogate, mylib"

Czy mogę dostosować sposób przechowywania tej nazwy pliku? np. czy chcę zastosować aliasy do określonych typów?

Czy istnieją inne podejścia? Mogę serializować całą rzecz w specjalny ciąg zamiast, który byłby mniejszy, ale znowu, to wydaje się niepewne.

Więc jakie są moje opcje, jeśli chcę zachować prymitywy z ich prawidłowym typem, jeśli są przechowywane w strukturze bez typu?

[Edytuj]

Normal Json:

{ 
    "foo":123 
} 

vs.

Nasza obecna wersja zastępcza:

{ 
    "foo": { 
        "$type":"Akka.Serialization.PrimitiveSurrogate, Akka", 
        "V":"123", 
        "T":1 
      } 
} 

mogę zastąpić V i T z tylko `" V ":" 123L "i przeanalizuj sufiks, ponieważ przechowujemy tylko int, float i decimal w tym typie, więc możemy łatwo mieć hardc oded descriminator.

Ale, nadal nie pozbyć się typu $ dla samego surogatu, chciałbym co najmniej skrócić to do "typu $": "Surogat" lub coś w tym kierunku.

[Edytuj ponownie] Mam go w dół do:

{"$type":"Akka.Util.PrimitiveSurrogate, Akka","V":"F123.456"} 

Ale tak naprawdę chce się pozbyć dłuższej TypeName i zastąpić alias jakoś.

[Edytuj ponownie ponownie]

Mam go do tego teraz:

{"$":"M123.456"} 

To wystarczająco dobre imo. Nie musimy wchodzić w interakcje z żadnym innym systemem json, jest to po prostu nasza struktura w obu końcach, więc skomponowany format działa, nawet jeśli nie jest ładny.

Odpowiedz

4

Jak ważna jest wielkość ładunku? Można na przykład osadzić metadane o typie każdego prymitywu, zasadniczo wiążąc kontrakt danych z danymi. Np:

{ 
    "someInteger": 123, 
    "$someInteger.clrType": " System.Int32" 
} 

EDIT:

Jeśli rozmiar bloku danych jest najważniejsze, można zrobić coś takiego:

{ 
    "someInteger.i": 123 
} 

To by obniżyć wzrost ładowności do dwóch znaków na wartości prymitywnej . Jestem prawie pewien, że kropka jest bezpieczna w użyciu jako separator; tj. identyfikator CLR nie powinien mieć identyfikatora "someInteger.i", chociaż podwójnie sprawdziłbym to w stosunku do specyfikacji (dozwolone znaki identyfikatora w CLR są regulowane przez następujący dokument, załącznik 7 http://www.unicode.org/reports/tr15/tr15-18.html#Programming%20Language%20Identifiers).

Jeśli naprawdę chcesz go skompaktować, możesz upuścić separator (.) I dodać nazwę właściwości z pojedynczym znakiem Unicode, który jest niedozwolony przez specyfikację CLR, do reprezentowania pożądanego typu pierwotnego. Trochę bezużyteczny, ale zmniejszyłby ładunek o kolejny bajt. ;-)

+0

Zdaję sobie sprawę, że jest to bardzo podobne do obecnego podejścia, ale jeśli poprawnie zinterpretuję Twój problem, nie widzę żadnego sposobu obejścia tego problemu. Informacja o typie musi gdzieś pójść, a jeśli nie chcesz podpowiedzi na samym typie, to gdzie indziej niż w samym serializowanym ładunku? –

+0

Yepp, zobacz moją edycję, dodałem wyjście z naszego obecnego podejścia zastępczego. –

+0

Jaki jest główny priorytet? Rozmiar ładunku? Przenośność/kompatybilność? Wydajność? –