2016-10-19 10 views
1

ストリームからJSONを受信して​​います。ScalaはJSONをいくつかのタイプに変換します

オブジェクトは、いくつかのスカラ型の1つで表すことができます。たとえば:{"userid":"blerk","name":"Fred"}User(userId:String, userName:String)

{"groupId":"zerk","name":"Accounting"}だろうGroup(groupId:String,groupName:String}

(現実のオブジェクトはより多くの要素を持っている)になります。

私はそれが重要な場合には、噴霧JSONを使用して、しかし、私が知りたいことはこれですよ:

私が機能を持っているしたいのですが、それが成功するまで、その順番はTry(myJson.convertTo[T])を行い、「変換」、およびタイプTの値を返します。

私の目的は、ある種の文字列マッチングのヒューリスティックスを使用して、それがどのようなタイプであるかを事前に突き止めずに、新しいケースが出現したときにリストに新しいタイプを追加できるようにすることです。私もこのようなコードを避けたいです

val t1=Try(myJson.convertTo[User]) 
if(t1.isSuccess) return t1.get 
val t2=Try(myJson.convertTo[Group]) 
if(t2.isSuccess) return t2.get 

悲しいことに、私はこの周りに私の小さな脳をラップし、任意の援助に感謝しています。

答えて

0

TryorElse methodを使用すると、あなたが求めていることを行うことができます。ここでは初めての試みです:

import scala.util.Try 
import spray.json._, DefaultJsonProtocol._ 

case class User(userId: String, userName: String) 
case class Group(groupId: String, groupName: String) 

implicit val userFormat: JsonFormat[User] = jsonFormat2(User) 
implicit val groupFormat: JsonFormat[Group] = jsonFormat2(Group) 

val groupJson = """{ "groupId": "zerk", "groupName": "Accounting" }""".parseJson 
val userJson = """{ "userId": "foo", "userName": "Foo McBar" }""".parseJson 

val result = Try(groupJson.convertTo[User]).orElse(Try(groupJson.convertTo[Group])) 

あなたがしようとする以上の2種類を持っている場合は、あなたが順番に試みを入れて_ orElse _でそれらをオーバー折り畳むことができます。

これは機能しますが、型の安全性を気にすると、タイプTry[Any]の結果が得られますが、実際に対処する場合は、結果に常にパターンを当てることができます原則としてそこに何かを持つことができます。あなたはきれいにしたい場合は

scala> userJson.convertTo[Either[Either[Group, String], User]] 
res5: Either[Either[Group,String],User] = Right(User(foo,Foo McBar)) 

:あなたは巣にEither秒を持っているが、これはまた、以上の2種類に一般

scala> groupJson.convertTo[Either[Group, User]] 
res3: Either[Group,User] = Left(Group(zerk,Accounting)) 

scala> userJson.convertTo[Either[Group, User]] 
res4: Either[Group,User] = Right(User(foo,Foo McBar)) 

より良いアプローチはEitherにデコードすることです2つ以上のタイプのうちの1つとして終わる可能性がある結果で作業する方法は、ShapelessCoproductは素敵な原理的な解決策です。あなたは、副産物のための独自のフォーマットを書く必要がありますが、それは比較的簡単なエクササイズです。

これは極端な型安全ルートです。気にしない場合は、orElseを使用してください。

+0

ありがとうございます。これは学習の練習なので、タイプセーフティーをあきらめるつもりはありません(少なくとも未だ)。そして可能なタイプがかなりあるので、ネストされた 'Either'ルートは完全に満足できるものではありません;-)。 Shapelessへのリンクは、ShapelessStreamが有用であるように見えるので、私はそれに感謝しています! – Mike

関連する問題