简体   繁体   English

Play Framework 2.1转换巨型JSON结构

[英]Play framework 2.1 transform giant json structure

I've been working with play 2.1's JSON Library, specifically combinators and transformers: http://www.playframework.com/documentation/2.1.4/ScalaJsonCombinators 我一直在使用play 2.1的JSON库,特别是组合器和转换器: http : //www.playframework.com/documentation/2.1.4/ScalaJsonCombinators

I have a use case where I have a large json structure (100+ keys). 我有一个用例,其中我有一个大的json结构(超过100个键)。 I need to update 20-30 of these values. 我需要更新这些值的20-30。 In my current understanding of the library, there are a few different ways I can achieve this: 在我目前对库的理解中,有几种不同的方法可以实现此目的:

1.Use an update transformer with "andThen" combinators: 1.使用带有“ andThen”组合器的更新转换器:

val jsonTransformer = (__ \ 'key2).json.pickBranch(
  (__ \ 'key21).json.update( 
    of[JsNumber].map{ case JsNumber(nb) => JsNumber(nb + 10) }
  ) andThen 
  (__ \ 'key23).json.update( 
    of[JsArray].map{ case JsArray(arr) => JsArray(arr :+ JsString("delta")) }
  )
)

I would have to chain 20+ "andThen" combinators...there's gotta be a better way, right? 我将不得不链接20多个“ andThen”组合器...总有一种更好的方法,对吗? It would be nice to have a transformer that takes a HashMap of values, and replaces the key/values of the hashmap with the ones in that particular json branch. 最好有一个接受值HashMap的转换器,然后用该特定json分支中的键/值替换该哈希图的键/值。 Can this be done? 能做到吗?

2.Another approach I thought of is creating a JsObject beforehand, and then just update the branch with one transform call: 2.我想到的另一种方法是事先创建一个JsObject,然后只用一个转换调用更新分支:

val jsonObject = Json.toJson(
  Map(
    "users" -> Seq(
      toJson(
        Map(
          "name" -> toJson("Bob"),
          "age" -> toJson(31),
          "email" -> toJson("bob@gmail.com")
        )
      ),
      toJson(
        Map(
          "name" -> toJson("Kiki"),
          "age" -> toJson(25),
          "email" -> JsNull
        )
      )
    )
  )
)

This is doable, but again could get quite big. 这是可行的,但又可能变得很大。

3.Define my own class for this data with implicit Reads/Writes formatters. 3.使用隐式读/写格式化程序为此数据定义我自己的类。 This would require me to build OO hierarchies and seems against some of the principles established by the library author with JSON-coast-to-coast: http://www.playframework.com/documentation/2.1.2/ScalaJsonTransformers . 这将需要我构建OO层次结构,并且似乎违反了库作者使用JSON-coast-to-coast建立的一些原则: http : //www.playframework.com/documentation/2.1.2/ScalaJsonTransformers

If you have any thoughts on which method would be best, I'd be interested to hear. 如果您对哪种方法最好有任何想法,我很想听听。 Thanks! 谢谢!

I used lift-json ( https://github.com/lift/lift/tree/master/framework/lift-base/lift-json/ ) with Play! 我在Play上使用了lift-json( https://github.com/lift/lift/tree/master/framework/lift-base/lift-json/ )! Framework (mixin LiftJson trait available at: https://github.com/tototoshi/lift-json-play-module ) for a similar use case as the ScalaJsonCombinators approach seemed complicated to maintain. 与ScalaJsonCombinators方法的维护类似,用于类似用例的框架(mixin LiftJson特性可从以下网址获得: https//github.com/tototoshi/lift-json-play-module )。

You can create case classes with only the fields that you think change (if all fields are changeable then create case classes with all JSON node names according to the JSON structure) and LiftJson provides functionality for mapping JSON strings to the case classes. 您可以仅使用您认为更改的字段来创建案例类(如果所有字段都是可更改的,则根据JSON结构使用所有JSON节点名称创建案例类),LiftJson提供了将JSON字符串映射到案例类的功能。 (No custom TypeHints are required unless you have to write custom serializer or deserializer. Just use the DefaultFormats.) (除非必须编写自定义序列化程序或反序列化程序,否则不需要自定义TypeHints。只需使用DefaultFormats。)

Once you have deserialized your JSON to case class objects, you can use the copy method on the case classes to replace the fields you want and serialize it back to JSON. 将JSON反序列化为case类对象后,可以在case类上使用copy方法替换所需的字段,并将其序列化回JSON。 This seemed to be more maintainable solution rather than calling the JSON node names directly all over the code. 这似乎是更可维护的解决方案,而不是直接在整个代码中调用JSON节点名称。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM