2017-09-21 1 views
0

J'ai un Seq de certaines chaînes de la plupart du temps comme ci-dessous:Json Rédige pour la classe personnalisée dans scala

val states = Seq(
    "CA" -> Seq("Los Angeles" -> Seq("SunsetBlvd", "Hollywood" -> Seq("W 8th St", "W 9th St")), "Pasadena"), 
    "WA" -> Seq("Seattle", "Redmond") 
) 

La classe de cas pour ce qui pourrait être

case class State(name: String, sub: Option[Seq[State]]) 

Et un Rédige implicite

implicit val stateWrites = Json.Writes[State] 

Espérant le convertir en Json comme

[ 
    { 
    "name": "CA", 
    "sub": [ 
     { 
     "name": "Los Angeles", 
     "sub": [ 
     { 
      "name": "SunsetBlvd" 
      }, 
      { 
      "name": "Hollywood", 
      "sub": [ 
       { 
       "name": "W 8th St" 
       }, 
       { 
       "name": "W 9th St" 
       } 
      ] 
      } 
     ] 
     } 
    ] 
    }, 
    { 
    "name": "WA", 
    "sub": [ 
     { 
     "name": "Seattle" 
     }, 
     { 
     "name": "Redmond" 
     } 
    ] 
    } 
] 

Comment puis-je modéliser correctement les données et être capable de convertir ce Seq en Json en utilisant les écritures?

Ou même changer le val states en un format approprié afin que je puisse facilement le convertir en Json?

Dans la classe de cas, l'un des champs est de type lui-même incorrect. Comment puis-je éviter cela dans la modélisation des données ou même le Seq?

+0

À quoi devrait ressembler votre json? – Reactormonk

+0

Quelque chose comme '[{" name ":" CA "," sub ": [{" name ":" Los Angeles "," sub ": [{" name ":" SunsetBlvd "}, {" name ":" Hollywood "," sub ": [{" name ":" W 8th St "}, {" nom ":" W 9th St "}]}}}' –

Répondre

0

je suis venu avec quelque chose comme ceci:

case class State(name: String, sub: Option[Seq[State]]) 

import play.api.libs.json._ 


implicit val optWrites = new Writes[Option[Seq[State]]] { 
    override def writes(o: Option[Seq[State]]) = { 
    if (o.isDefined) { 
     Json.toJson(o.get)(stateSeqWrites) 
    } else { 
     JsNull 
    } 
    } 
} 

implicit val stateWrites = new Writes[State] { 
    def writes(state: State) = { 
    val l: Seq[(String, JsValueWrapper)] = Seq("name" -> JsString(state.name)) 
    val ll: Seq[(String, JsValueWrapper)] = if (state.sub.isDefined) { 
     val subValue: JsValueWrapper = Json.toJson(state.sub)(optWrites) 
     l :+ ("sub" -> subValue) 
    } else { 
     l 
    } 

    Json.obj(ll : _*) 
    } 
} 

implicit val stateSeqWrites: Writes[Seq[State]] = new Writes[Seq[State]] { 
    override def writes(s: Seq[State]) = { 
    JsArray(s.map(Json.toJson(_)(stateWrites))) 
    } 
} 

val states = Seq(
    State("CA", Some(Seq(State("Los Angeles", Some(Seq(State("SunsetBlvd", None), State("Hollywood", Some(Seq(State("W 8th St", None), State("W 9th St", None)))), State("Pasadena", None))))))), 
    State("WA", Some(Seq(State("Seattle", None), State("Redmond", None)))) 
) 

val json = Json.toJson(states) 

println(json.toString()) 

probablement obtiendrez peut-être simplifié, mais il est tard dans la nuit ici;) Il fait ce que vous avez besoin :)

0

Cette information a conceptuellement une structure arborescente. Mon conseil est de menace avec juste une classe de cas normal, pour simplifier la mise en forme JSON et d'avoir une structure beaucoup plus sémantique:

case class Tree(name: String, sub: Option[List[Tree]]) 

Et votre formatter serait comme ceci:

implicit val repositoryFormat: Format[Tree] = (
    (__ \ 'name).format[String] ~ 
     (__ \ 'sub).lazyFormatNullable(implicitly[ Format[ List[Tree] ]]) 
    )(Tree.apply, unlift(Tree.unapply)) 

Notez que j'ai utilisé lazyFormatNullable pour traiter la référence récursive à Tree dans sub. Pour simuler le Json que vous avez posté, j'ai fait la traduction à la structure de classe Tree.

// The tree leaves 
    val hollywoodLeaves = Some(Tree("W 8th St", None) :: Tree("W 9th St", None) :: Nil) 
    val losAngelesLeaves = Some(Tree("SunsetBlvd", None) :: Tree("Hollywood", hollywoodLeaves) :: Nil ) 

    // The two trees in your array 
    val firstTree = Tree("CA", Some(Tree("Los Angeles", losAngelesLeaves) :: Nil)) 
    val secondTree = Tree("WA", Some(Tree("Seattle", None) :: Tree("Redmond", None) :: Nil)) 

    // Your root array 
    val treeArray = firstTree :: secondTree :: Nil 

    // Conversion to json 
    val json = Json.toJson(treeArray)