如何解析包含在 Scala 中始终更改名称的字段的 json?

How to parse a json containing a field that always has a changed name in Scala?

我目前有一个来自 API 的非常大的 json 响应,我想 json 解析它。我的应用程序正在使用 play 和 Scala。 为此,我使用了 case classes,稍后我将使用隐式解析它。但是现在我已经意识到在我的一个案例中 classes 我有一个总是在更改名称的字段。如何解析它?

例如,我有 json 响应的这一部分:

"customerInfo": {
 "number": "123456XXXXXX7891",
    "email": "randomname@gmail.com",
    "billingFirstName": "Random",
    "billingLastName": "Name"
  },

我将用这个解析:

case class CustomerInfo (
number: String,
email: String,
billingFirstName: String,
billingLastName: String
)

但是我在 json 中有一个变化的字段,看起来像这样:

    "Check": {
      "5c123456":
        "{random numbers inside here}"
    }

这个字段“5c123456”总是在变化,永远不会相同"name"。 我将如何解析它?如果没有,我是否可以忽略这种情况 class 检查并仍然解析 json 的其余部分?非常感谢任何帮助。

已编辑以添加额外信息

澄清一下,我想做的是能够像这样解析它:

val result = Json.fromJson[RootInterface](res.json).get

这是整个响应的示例:

    val response = : """{
  "per_page": 50,
  "current_page": 1,
  "next_page_url": "http:\/\/testapi.com\/api\/v3\/testing\/list?page=2",
  "prev_page_url": null,
  "from": 1,
  "to": 50,
  "data": [
    {
      "customerInfo": {
        "number": "1234",
        "email": "felix@ytesting.com",
        "billingFirstName": "Felix",
        "billingLastName": "Testing"
      },
      "updated_at": "2018-12-13 16:10:08",
      "created_at": "2018-12-13 14:06:54",
      "fx": {
        "merchant": {
          "originalAmount": 1234,
          "originalCurrency": "EUR",
          "convertedAmount": 1234,
          "convertedCurrency": "EUR"
        }
      },
      "raw": {
        "Check": {
          "5c1283dad": "{\"id\":\"1234-5678-4da1-a3ea-5aa0c2b8a3f3\",\"status\":\"TEST\",\"risk_score\":0,\"descriptions\":{},\"testRuleId\":null,\"triggeredExceptionRuleId\":null,\"reason\":null}"
        }
      },
      "acquirer": {
        "type": "TESTCARD"
      },
      "transaction": {
        "merchant": {
          "referenceNo": "12345",
          "status": "TEST",
          "operation": "TEST",
          "type": "AUTH",
          "message": "TESTING",
          "customData": "1234",
          "created_at": "2018-12-12 15:10:07",
          "transactionId": "12345"
        }
      },
      "refundable": false,
      "merchant": {
        "id": 1234,
        "name": "Felix Testing",
        "allowPartialRefund": false,
        "allowPartialCapture": false
      },
      "ipn": {
        "sent": true,
        "merchant": {
          "transactionId": "123456789",
          "referenceNo": "1234",
          "amount": 1234,
          "currency": "EUR",
          "date": 1544717407,
          "code": "42",
          "message": "TESTING",
          "operation": "TEST",
          "type": "AUTH",
          "status": "DECLINED",
          "customData": "12345",
          "paymentType": "TESTCARD",
          "authTransactionId": "123456",
          "descriptor": "Felix Testing",
          "token": "123456789token",
          "convertedAmount": 1234,
          "convertedCurrency": "EUR",
          "ipnType": "TESTIP",
          "_queueReadCountKey": 1
        }
      }
    }
  ]
}"""

我有这些案例分类:

case class Acquirer(
  `type`: String
)

case class CustomerInfo (
  number: String,
  email: String,
  billingFirstName: String,
  billingLastName: String
                        )

case class Data (
    customerInfo: CustomerInfo,
    updated_at: String,
    created_at: String,
    fx: Fx,
    raw: Option[Raw],
    acquirer: Acquirer,
    transaction: transaction,
    refundable: Boolean,
    merchant: Merchant2,
    ipn: Ipn
  )

  case class transaction(
  merchant : Merchant1
                        )

case class Fx (
  merchant: Merchant
)

case class Ipn (
 sent: Boolean,
 merchant: Merchant3
 )

case class Merchant (
originalAmount: Int,
originalCurrency: String,
convertedAmount: Int,
convertedCurrency: String
)

case class Merchant1 (
 referenceNo: String,
 status: String,
 operation: String,
`type`: String,
message: String,
customData: String,
created_at: String,
transactionId: String
)

case class Merchant2 (
   id: Int,
   name: String,
   allowPartialRefund: Boolean,
   allowPartialCapture: Boolean
   )

case class Merchant3 (
   transactionId: String,
   referenceNo: String,
   amount: Int,
   currency: String,
   date: Int,
   code: String,
   message: String,
   operation: String,
   `type`: String,
   status: String,
   customData: String,
   paymentType: String,
   authTransactionId: String,
   descriptor: String,
   token: String,
   convertedAmount: Int,
   convertedCurrency: String,
   ipnType: String,
   _queueReadCountKey: Int
)
                 )

case class Raw(Check: Map[String, String])


case class RootInterface (
   per_page: Int,
   current_page: Int,
   next_page_url: String,
   prev_page_url: String,
   from: Int,
   to: Int,
   data: List[Data]
 )

这些隐式:

implicit val RootInterface: Format[RootInterface] = Json.format[RootInterface]
  implicit val Data: Format[Data] = Json.format[Data]
  implicit val CustomerInfo: Format[CustomerInfo] = Json.format[CustomerInfo]
  implicit val Fx: Format[Fx] = Json.format[Fx]
  implicit val Transaction: Format[transaction] = Json.format[transaction]
  implicit val Acquirer: Format[Acquirer] = Json.format[Acquirer]
  implicit val Merchant: Format[Merchant] = Json.format[Merchant]
  implicit val Merchant1: Format[Merchant1] = Json.format[Merchant1]
  implicit val Merchant2: Format[Merchant2] = Json.format[Merchant2]
  implicit val Merchant3: Format[Merchant3] = Json.format[Merchant3]
  implicit val Ipn: Format[Ipn] = Json.format[Ipn]
  implicit val jsonFormat: Format[Raw] = Json.format[Raw]

如评论中所述,动态字段使用 Map 处理。这是一个例子:

像这样定义 case-class

import play.api.libs.json._

case class MyObject(Check: Map[String, String])

定义隐式格式:

object MyObject {
  implicit val jsonFormat: OFormat[MyObject] = Json.format[MyObject] 
}

使用 validate 从 Json

创建 case-class
val json = Json.parse("""{ "Check": {
      "5c123456":
        "123239"
    }}""")

json.validate[MyObject] // > JsSuccess(MyObject(Map(5c123456 -> 123239)),)

这是要检查的 Scalafiddle:Scalafiddle

这里是相应的文档:JSON-automated-mapping