2015-03-12 12 views
6

Wir verwenden Json.net für die Serialisierung. und wir möchten, dass jede Art von benutzerdefinierter Klasse/Nachricht serialisiert werden kann.Ersatz int, float und dezimal mit Json.NET

Eine Sache, die Json.net kann nicht aus der Box unterstützt, wenn Sie ein int speichern, float oder ein decimal in einem object Feld. z.B.

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

wenn ich speichern ein int, float oder decimal im Etwas Feld, wird es in sein deserialisiert entweder ein long oder ein double (als json.net nichts mehr als denke, die Art des primitiven tun kann die json („foo“: 123 < - int oder lang).

im völlig bewusst, dass ich eine richtige Art auf dem Grundstück nutzen und verschiedene Hinweise eingestellt

Aber ich möchte dies für jede zufällige lösen Klasse/Nachricht

Mein aktueller Ansatz ist ein benutzerdefinierter JsonConverter, der sich mit den oben genannten Typen befasst und diese dann in einen Ersatztyp serialisiert, der den Wert als String und einen Diskriminator für den Typ enthält. Und dann auf ReadJson wandle ich das wieder in den richtigen Typ.

Es gibt viel Überhitzung dafür. speziell für den Typenname des Ersatztyps. "foo.bar.baz.PrimitiveSurrogate, mylib"

Kann ich anpassen, wie dieser Typname gespeichert wird? z.B. wenn ich Aliase auf bestimmte Typen anwenden möchte?

Gibt es andere Ansätze? Ich könnte das Ganze in eine spezielle Zeichenfolge serialisieren, die kleiner wäre, aber dann wieder, das fühlt sich zweifelhaft an.

Also was sind meine Optionen hier, wenn ich Primitive mit ihrem korrekten Typ behalten möchte, wenn sie in einer untypisierten Struktur gespeichert werden?

[Bearbeiten]

Normale Json:

{ 
    "foo":123 
} 

vs.

Unsere aktuelle Surrogat-Version:

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

I V und T mit nur ersetzen könnte `" V ":" "123L" und analysiere das Suffix, da wir nur int, float und decimal in diesem Typ speichern, so dass wir leicht ein Hardc haben können Deskriptor.

Aber das wird immer noch nicht den $ -Typ für das Surrogat selbst loswerden, ich möchte das zumindest auf etwas wie "$ type" verkürzen: "Surrogate" oder etwas in dieser Richtung.

[Bearbeiten wieder] Ich habe es bis auf:

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

Aber ich würde wirklich wollen, die langen Typnamen loszuwerden und ersetzen mit einem irgendwie Alias.

[Bearbeiten wieder wieder]

Ich habe es schon jetzt auf diese nach unten:

{"$":"M123.456"} 

Das gut genug imo. Wir müssen nicht mit anderen json-Systemen zusammenarbeiten, es ist nur unser Framework in beiden Enden, so dass das erfundene Format funktioniert, auch wenn es nicht schön ist.

Antwort

4

Wie wichtig ist die Größe der Nutzlast? Sie könnten zum Beispiel Metadaten über den Typ jedes Grundelements einbetten und im Wesentlichen einen Datenvertrag mit den Daten bündeln. ZB:

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

EDIT:

Wenn Nutzlastgröße am wichtigsten ist, können Sie etwas tun könnte, wie:

{ 
    "someInteger.i": 123 
} 

, dass die Nutzlast Erhöhung auf zwei Zeichen pro Grundwert bringen würde . Ich bin mir ziemlich sicher, dass der Punkt als Trennzeichen sicher ist; d. h. es sollte nicht möglich sein, dass ein CLR-Identifikator den Identifizierer "someInteger.i" hat, obwohl ich dies anhand der Spezifikation überprüfen würde (zulässige Identifiziererzeichen in der CLR werden durch das folgende Dokument, Anhang 7 http://www.unicode.org/reports/tr15/tr15-18.html#Programming%20Language%20Identifiers, geregelt).

Wenn Sie es wirklich komprimieren möchten, können Sie das Trennzeichen (.) Löschen und den Eigenschaftsnamen mit einem einzelnen Unicode-Zeichen versehen, das von der CLR-Spezifikation nicht zugelassen wird, um den gewünschten primitiven Typ darzustellen. Ein bisschen hacky, aber es würde die Nutzlast um ein weiteres Byte reduzieren. ;-)

+0

Ich weiß, das ist ziemlich ähnlich zu Ihrem derzeitigen Ansatz, aber wenn ich Ihr Problem richtig interpretiere, sehe ich keinen Weg um es herum. Die Typ-Info muss irgendwo hingehen, und wenn Sie keine Hinweise auf den Typ selbst, dann wo anders als in der serialisierten Nutzlast selbst wollen? –

+0

Yepp, siehe meine Bearbeitung, ich habe die Ausgabe unseres aktuellen Surrogat-Ansatzes hinzugefügt. –

+0

Was ist die Hauptpriorität? Nutzlastgröße? Portabilität/Kompatibilität? Performance? –