【问题标题】:Retrieving null values from json using circe-optics使用 circe-optics 从 json 中检索空值
【发布时间】:2020-02-19 13:42:33
【问题描述】:

我的 json 看起来像这样:

{
    "cards": [
        {
            "card_id":"1234567890",
            "card_status":"active",
            "card_expiration":{
                "formatted":"01/20"
            },
            "debit":{
                "masked_debit_card_number":"1111 **** **** 1111",
            }
        },
        {
            "card_id":"1234567891",
            "card_status":"active",
            "card_expiration":null,
            "debit":{
                "masked_debit_card_number":"2222 **** **** 2222",
            }
        }
    ]
}

我正在尝试使用此函数检索所有 card_expiration 字段值:

def getExpirations(json: Json) =
    root
        .cards
        .each
        .filter(root.card_status.string.exist(_ == "active"))
        .card_expiration
        .selectDynamic("formatted")
        .string
        .getAll(json)

问题是,上面的表达式只返回一个结果 - 对于第一张卡片,但我真的需要得到类似 List(Some("01/20"), None) 的东西!在这种情况下我该怎么办?

【问题讨论】:

  • 所以,您想要nulls,但您使用的是功能性 json 库...有趣的选择。或者你在接受JsonNull 吗?
  • 您要做的只是删除.selectDynamic.string。你可以得到一个List[Json]...然后你映射它们以从JObjects中提取字段,然后为JNulls获取None。
  • 知道如何在代码中做到这一点吗? :) 在card_expiration 之后使用.getAll(json) 不会编译,因为它需要一个int(索引?)。直接对 card_expiration 字段返回的内容进行操作非常困难,因为它是 circe-optics 正在使用的库内部的东西 - 单片眼镜。
  • 好的,我想我设法做到了,但它涉及的手动工作比我想要的要多。没有更简单的方法吗?

标签: json scala circe circe-optics


【解决方案1】:

问题是当您完成formatted 步骤时,您不再匹配null 到期时间。你可以这样做:

import io.circe.Json, io.circe.optics.JsonPath.root

def getExpirations(json: Json) =
  root
    .cards
    .each
    .filter(root.card_status.string.exist(_ == "active"))
    .card_expiration
    .as[Option[Map[String, String]]]
    .getAll(json)

或者:

import io.circe.Json, io.circe.generic.auto._, io.circe.optics.JsonPath.root

case class Expiration(formatted: String)

def getExpirations(json: Json) =
  root
    .cards
    .each
    .filter(root.card_status.string.exist(_ == "active"))
    .card_expiration
    .as[Option[Expiration]]
    .getAll(json)

然后:

scala> getExpirations(io.circe.jawn.parse(doc).right.get)
res0: List[Option[Expiration]] = List(Some(Expiration(01/20)), None)

如果没有更多上下文,我认为这对于 circe-optics 来说是一个很好的用例。你可能最好解码成案例类,或者使用游标。如果你能提供更多信息,那就更容易说出来了。

【讨论】:

  • 我有大量的 API 可以返回各种数据,而企业希望我开发一个能够使用配置文件来使用所有这些数据的程序 - 所以应该包括很少甚至没有编码.原因是如果开发了新的 API,我不应该编写任何 API 特定的代码,而是使用某种 DSL 来提取他们需要的数据。我的第一个想法是使用 Baeldung 上描述的 JsonPath,但后来我想到了 circe-optics,因为它更原生于 scala。无论如何,我做了与上述类似的事情,并在您的帖子之后改进了代码。谢谢:)
  • 顺便说一句。这些配置文件将是一组封装类似于上面的表达式逻辑的类(这只是一个简单用例的简化形式) - 每个使用的 api 一个。没有人说配置文件不能是 Scala 代码 ;)
猜你喜欢
  • 2019-08-16
  • 2018-10-06
  • 1970-01-01
  • 2011-10-31
  • 2018-05-08
  • 2019-05-19
  • 1970-01-01
  • 1970-01-01
  • 2021-01-24
相关资源
最近更新 更多