【问题标题】:Use circe to preprocess dot-notation style fields使用 circe 预处理点符号样式字段
【发布时间】:2017-10-18 20:09:07
【问题描述】:

我有一些 json,其中包含一些字段,这些字段被扁平化为 bson-ish 格式,如 {"foo.bar" : "bash"}。我想将其转换为以下表示 {"foo" : { "bar" : "bash"}} 并想知道我会在哪里做这样的操作。使问题复杂化的是,可能有多个此类字段需要正确合并,例如{"foo.bar" : "a", "foo.bash" : "b", "foo.baz" : "c"} -> {"foo" : { "bar" : "a", "bash" : "b", "baz" : "c"}}.

【问题讨论】:

    标签: json scala circe


    【解决方案1】:

    这是一个快速实现:

    import io.circe.Json
    
    val Dotted = "([^\\.]*)\\.(.*)".r
    
    def expandDotted(j: Json): Json = j.arrayOrObject(
      j,
      js => Json.fromValues(js.map(expandDotted)),
      _.toList.map {
        case (Dotted(k, rest), v) => Json.obj(k -> expandDotted(Json.obj(rest -> v)))
        case (k, v) => Json.obj(k -> expandDotted(v))
      }.reduceOption(_.deepMerge(_)).getOrElse(Json.obj())
    )
    

    我还没有真正使用或详细测试过它,但它似乎可以工作:

    scala> import io.circe.literal._
    import io.circe.literal._
    
    scala> val j1 = json"""{"foo.bar" : "a", "foo.bash" : "b", "foo.baz" : "c"}"""
    j1: io.circe.Json =
    {
      "foo.bar" : "a",
      "foo.bash" : "b",
      "foo.baz" : "c"
    }
    
    scala> expandDotted(j1)
    res1: io.circe.Json =
    {
      "foo" : {
        "baz" : "c",
        "bash" : "b",
        "bar" : "a"
      }
    }
    

    而且嵌套更深:

    scala> expandDotted(json"""{ "x.y.z": true, "a.b": { "c": 1 } }""")
    res2: io.circe.Json =
    {
      "a" : {
        "b" : {
          "c" : 1
        }
      },
      "x" : {
        "y" : {
          "z" : true
        }
      }
    }
    

    只是为了确认它不会与未加点的键混淆:

    scala> expandDotted(json"""{ "a.b": true, "x": 1 }""").noSpaces
    res3: String = {"x":1,"a":{"b":true}}
    

    请注意,在“冲突”(导致 JSON 对象和非对象 JSON 值或多个非对象值的路径)的情况下,行为是 Json#deepMerge 的行为:

    scala> expandDotted(json"""{ "a.b": true, "a": 1 }""").noSpaces
    res4: String = {"a":1}
    
    scala> expandDotted(json"""{ "a": 1, "a.b": true }""").noSpaces
    res5: String = {"a":{"b":true}}
    

    ...这可能是你想要的,但在这些情况下你也可能让它失败,或者不扩展碰撞路径,或者做你能想到的任何其他事情。

    【讨论】:

    • 如果json中有数组,你会怎么做?
    猜你喜欢
    • 1970-01-01
    • 2020-05-10
    • 1970-01-01
    • 2010-09-18
    • 2014-01-17
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 2015-06-27
    相关资源
    最近更新 更多