2016-10-06 6 views
5

Da ich mit generischen Typ beschäftigen, daher kann ich nicht bestimmte Fallklassen verwenden. Dann habe ich ein generisches Util erstellt, das generische Objekte serialisiert und deserialisiert.json4s serialisieren und deserialisieren generischen Typ

import org.json4s 
import org.json4s.Formats._ 
import org.json4s.native.JsonMethods._ 

object JsonHelper { 
    def json2Object[O](input: String) : O = { 
    parse(json4s.string2JsonInput(input)).asInstanceOf[O] 
    } 
    def object2Json[O](input: O) : String = { 
    write(input).toString 
    } 
} 

Der Compiler führt den Fehler:

No JSON serializer found for type O. Try to implement an implicit Writer or JsonFormat for this type. write(input).toString

Dies sollte zur Laufzeit geworfen werden, aber warum es bei der Kompilierung geworfen?

+0

Wie läuft es in Ihrem Kopf? Wenn 'O' etwas sein kann, wie wird Json4s dann wissen, was in allen Fällen zu tun ist? Ihre 'write (input)' Sache wird funktionieren, solange ein Writer oder ein JsonFormat für O definiert ist. Zur Kompilierzeit wird das nicht gefunden – mfirry

+1

@mfirry So, wie kann jackson mit Java-Objekten arbeiten? Es verwendet Reflexion richtig? Und warum unterscheidet es sich von Scala? –

Antwort

7

In einem Kommentar oben, werden Sie gefragt " Also, wie kann jackson mit Java-Objekt arbeiten? Es verwendet Reflexion richtig? Und warum ist es anders als Scala? ", Die auf das Herz dieser Frage kommt.

Der "native" Serializer von json4s, den Sie importiert haben, verwendet die Kompilierungsreflexion, um die Writer zu erstellen.

Jackson verwendet Laufzeitreflexion, um das gleiche zu tun.

Die Kompilierungsversion ist effizienter; Die Laufzeitversion ist flexibler.

Um die Kompilierungsversion verwenden zu können, müssen Sie dem Compiler genügend Informationen geben, um die richtige Writer basierend auf dem deklarierten Typ des zu serialisierenden Objekts auszuwählen. Dies schließt sehr generische Schreibmethoden wie die von Ihnen vorgeschlagene aus. Unter @ TimP's Antwort finden Sie, wie Sie Ihren Code für diese Version reparieren können.

Um die Laufzeitversion zu verwenden, können Sie Jackson über das org.json4s.jackson.JsonMethods._ Paket verwenden. Siehe https://github.com/json4s/json4s#jackson

1

In diesem Beispiel haben Sie einen Deal mit generischen Typen, Scala, wie andere jvm Sprachen, hat type erasing Mechanismus zur Kompilierzeit (Fehlermeldung zur Kompilierzeit kann keine Nachricht über generische in einem Ganzen enthalten), also versuchen Sie es

(implicit tag: ClassTag[T]) 

it's ähnlich wie Sie beispielsweise mit generischen, aber mit Jackson: dieses Fragment zur Unterzeichnung beider Verfahren anzuhängen. HTH

5

Der von Ihnen veröffentlichte Compilerfehler stammt von this location in the json4s code. Die write Funktion, die Sie aufrufen, nimmt eine implizite JSON Writer, die Methode kann beliebige Typen annehmen. Es ist bei der Kompilierung gefangen, weil implizite Argumente die gleiche Art und Weise ausdrücklich diejenigen sind kompiliert werden - dann ist es, als ob Sie hatte:

def f(a: Int, b: Int) = a + b 
f(5) // passed the wrong number of arguments 

Ich habe ein wenig Mühe zu sehen genau, welche write Methode Sie aufrufen hier - - Die json4s Bibliothek ist ziemlich groß und die Dinge sind überlastet. Können Sie die deklarierte write Methode, die Sie verwenden, einfügen? Es ist fast sicher eine Signatur wie folgt hat:

def write[T](value: T)(implicit writer: Writer[T]): JValue 

Wenn es wie die oben schaut, wie es so in Ihrer Methode einschließlich der impliziten Verfasser Parameter versuchen:

object JsonHelper { 
    def json2Object[O](input: String)(implicit reader: Reader[O]) : O = { 
    parse(json4s.string2JsonInput(input)).asInstanceOf[O] 
    } 
    def object2Json[O](input: O)(implicit writer: Writer[O]) : String = { 
    write(input).toString 
    } 
} 
Verwandte Themen