2017-02-10 89 views
1

字符串转换成JSON我需要帮助JSON字符串解析成使用playJson斯卡拉 - 使用播放JSON

我写了一个格式,但我不知道如何处理嵌套数组斯卡拉类。

凡公文包类是

case class Document(content: String, score: Double, size: Int, path:String) 

和格式化

implicit val similarHashFormatter: Format[SimilarHash] = (
    ((__ \ "hits" \ "hits" \\ "fields")(0) \ "content_hash")(0).format[String] and 
    (__ \ "hits" \ "hits" \\ "_score").format[Double] and 
    ((__ \ "hits" \ "hits" \\ "fields")(0) \ "ast_size")(0).format[Int] and 
    ((__ \ "hits" \ "hits" \\ "fields")(0) \ "path")(0).format[String] 
) (SimilarHash.apply, unlift(SimilarHash.unapply)) 

这是我的源JSON

{ 
    "hits": { 
    "hits": [ 
     { 
     "score": 1.5204661, 
     "fields": { 
      "size": [ 
      557645 
      ], 
      "path": [ 
      "/user/ubuntu/app 
      ], 
      "content": [ 
      "images" 
      ] 
     } 
     }, 
     {   
     "score": 1.5199462, 
     "fields": { 
      "size": [ 
      556835 
      ], 
      "path": [ 
      "/user/ubuntu/app 
      ], 
      "content": [ 
      "documents" 
      ] 
     } 
     } 
    ] 
    } 
} 

任何想法?

+0

什么是您的Scala类的定义是什么样子?大多数情况下,使用case类的Json.format宏来处理更复杂的模型是最简单的。 – josephpconley

+0

@josephpconley我刚刚添加了Document case类,任何示例如何使用Json.format宏? –

回答

0

我想通了基于遗忘的评论,但无需创建多个读取解决方案。

implicit val docReader: Reads[Document] = (
     (__ \ "fields" \ "content")(0).read[String] and 
     (__ \ "_score").read[Double] and 
     ((__ \ "fields") \ "size")(0).read[Int] and 
     ((__ \ "fields") \ "path")(0).read[String] 
    ) (Document.apply _) 


    implicit val docsReader: Reads[Documents] = (
     (__ \ "hits" \ "max_score").read[Double] and 
     (__ \ "hits" \ "hits").read[Seq[Document]] 
    ) (Documents.apply _) 

... 最后

val response = Json.parse(inputStream).asOpt[Documents] 
1

您可以通过为每个字段创建自定义Reads分别如下做到这一点:

import play.api.libs.json._ 
    import play.api.libs.functional.syntax._ 

    case class Document(content: String, score: Double, size: Int, path:String) 

    val jsonString = """{ 
         "hits": { 
          "hits": [ 
           { 
            "score": 1.5204661, 
            "fields": { 
             "size": [ 
              557645 
             ], 
             "path": [ 
              "/user/ubuntu/app" 
             ], 
             "content": [ 
              "images" 
             ] 
            } 
           }, 
           { 
            "score": 1.5199462, 
            "fields": { 
             "size": [ 
              556835 
             ], 
             "path": [ 
              "/user/ubuntu/app" 
             ], 
             "content": [ 
              "documents" 
             ] 
            } 
           } 
          ] 
         } 
        }""" 

    val playJson = Json.parse(jsonString) 

    val contentReads = new Reads[String] { 
    override def reads(json: JsValue): JsResult[String] = json \ "hits" match { 
     case JsDefined(o: JsObject) => 
     o \ "hits" match { 
      case JsDefined(arr: JsArray) => 
      arr.value.head \ "fields" match { 
       case JsDefined(fieldObj: JsObject) => 
       fieldObj \ "content" match { 
        case JsDefined(contentArr: JsArray) => 
        JsSuccess(Json.stringify(contentArr.value.head)) 
        case _ => JsError("""Can't read hits \ hits \ fields \ content""") 
       } 
       case _ => JsError("""Can't read hits \ hits \ fields""") 
       case _ => JsError("""Can't read hits \ hits""") 
      } 
      case _ => JsError("Can't read hits") 
     } 
    } 
    } 

    val sizeReads = new Reads[Int] { 
    override def reads(json: JsValue): JsResult[Int] = json \ "hits" match { 
     case JsDefined(o: JsObject) => 
     o \ "hits" match { 
      case JsDefined(arr: JsArray) => 
      arr.value.head \ "fields" match { 
       case JsDefined(fieldObj: JsObject) => 
       fieldObj \ "size" match { 
        case JsDefined(contentArr: JsArray) => 
        JsSuccess(Json.stringify(contentArr.value.head).toInt) 
        case _ => JsError("""Can't read hits \ hits \ fields \ size""") 
       } 
       case _ => JsError("""Can't read hits \ hits \ fields""") 
      } 
      case _ => JsError("""Can't read hits \ hits""") 
     } 
     case _ => JsError("Can't read hits") 
    } 
    } 

    val scoreReads = new Reads[Double] { 
    override def reads(json: JsValue): JsResult[Double] = json \ "hits" match { 
     case JsDefined(o: JsObject) => 
     o \ "hits" match { 
      case JsDefined(arr: JsArray) => 
      arr.value.head \ "score" match { 
       case JsDefined(score: JsValue) => 
       JsSuccess(Json.stringify(score).toDouble) 
       case _ => JsError("""Can't read hits \ hits \ score""") 
      } 
      case _ => JsError("""Can't read hits \ hits""") 
     } 
     case _ => JsError("Can't read hits") 
    } 
    } 

    val pathReads = new Reads[String] { 
    override def reads(json: JsValue): JsResult[String] = json \ "hits" match { 
     case JsDefined(o: JsObject) => 
     o \ "hits" match { 
      case JsDefined(arr: JsArray) => 
      arr.value.head \ "fields" match { 
       case JsDefined(fieldObj: JsObject) => 
       fieldObj \ "path" match { 
        case JsDefined(contentArr: JsArray) => 
        JsSuccess(Json.stringify(contentArr.value.head)) 
        case _ => JsError("""Can't read hits \ hits \ fields \ path""") 
       } 
       case _ => JsError("""Can't read hits \ hits \ fields""") 
      } 
      case _ => JsError("""Can't read hits \ hits""") 
     } 
     case _ => JsError("Can't read hits") 
    } 
    } 

    implicit val documentReads: Reads[Document] = (
    contentReads and 
    scoreReads and 
    sizeReads and 
    pathReads 
)(Document.apply _) 

    val document = playJson.validate[Document].get 
//result: Document("images",1.5204661,557645,"/user/ubuntu/app")