2017-06-28 5 views
0

Ich bin es gewohnt, mit sacla spray-json JSON-Daten zu serialisieren und zu deserialisieren. Aber es hat mich für eine lange Zeit ein Problem verwirren: die json Daten Angenommen ist:Scala Spray-JSON Typ übereinstimmen

{"a":"123"} 

aber manchmal kann es sein:

{"a":123} or {"a":123.0} 

Problem ist, dass ich die Daten nicht konw im Voraus eingeben, kann es String oder Int oder Doule sein.

Bei Verwendung von Spray-Json-Framework muss ich das Datenformat im Voraus bestimmen. Unten ist mein Code:

case class Input(a:Either[String,Numeric[Either[Int,Doule]]]) 

object SelfJsonProtocol extends DefaultJsonProtocol { 
    // format the json type into scala type. 
    implicit val InputFormat = jsonFormat1(Input) 
} 

Aber das war falsch, wenn es kompilieren. Kann mir jemand helfen?

+0

Warum Sie nicht nur den Datentyp definieren doppelt zu sein und jeden Wert konvertieren, die zu verdoppeln kommt? –

+0

@RameshMaharjan, Aus irgendeinem externen Grund kann ich den Dateityp nicht vorher bestimmen. – Yang

+0

müssen Sie den Datentyp nicht kennen. Definieren Sie Ihre Fallklasse als doubleType und parsen Sie den Wert, um sonst 0,0 zu erhalten. –

Antwort

1

Eigentlich kann der Typ Beide in Ihrer Fallklasse funktionieren, wenn Sie es ein wenig vereinfachen. Verwende entweder [Double, String]. Auf diese Weise werden Ints automatisch als Doubles analysiert.

Beispiel:

import spray.json._ 

case class DoubleTest(a: Either[Double, String]) 

object MyJsonProtocol extends DefaultJsonProtocol { 
    implicit val doubleTestFormat = jsonFormat1(DoubleTest) 
} 

import MyJsonProtocol._ 

val json = """[{"a":"123"}, {"a":123}, {"a":123.0}]""" 
val ast = JsonParser(json) 
val DTs = ast.convertTo[List[DoubleTest]] 
DTs.map { dt => 
    dt.a match { 
    case Left(d) => { println("double found"); d } 
    case Right(d) => { println("string found"); d.toDouble } 
    } 
} 

Ausgang:

json: String = [{"a":"123"}, {"a":123}, {"a":123.0}] 
ast: spray.json.JsValue = [{"a":"123"},{"a":123},{"a":123.0}] 
DTs: List[DoubleTest] = List(DoubleTest(Right(123)), DoubleTest(Left(123.0)), DoubleTest(Left(123.0))) 
string found 
double found 
double found 
res35: List[Double] = List(123.0, 123.0, 123.0) 
+0

Danke eine Milliarde, das funktioniert für mich, und wenn ich entweder [String, Numeric [Entweder [Int, Doule]]] code, scheint es notwendig, eine weitere Typübereinstimmung zu machen, aber es sieht so überflüssig aus. – Yang