简体   繁体   English

使用 Scala Argonaut 解析 JSON 数组

[英]Parse JSON array using Scala Argonaut

I'm using Scala & Argonaut, trying to parse the following JSON:我正在使用 Scala 和 Argonaut,试图解析以下 JSON:

[
    {
        "name": "apple",
        "type": "fruit",
        "size": 3
    },
    {
        "name": "jam",
        "type": "condiment",
        "size": 5
    },
    {
        "name": "beef",
        "type": "meat",
        "size": 1
    }
]

And struggling to work out how to iterate and extract the values into a List[MyType] where MyType will have name, type and size properties.并努力解决如何迭代并将值提取到List[MyType] ,其中MyType将具有名称、类型和大小属性。

I will post more specific code soon (i have tried many things), but basically I'm looking to understand how the cursor works, and how to iterate through arrays etc. I have tried using \\\\ (downArray) to move to the head of the array, then :->- to iterate through the array, then --\\ (downField) is not available (at least IntelliJ doesn't think so).我很快会发布更具体的代码(我尝试了很多东西),但基本上我想了解光标的工作原理,以及如何遍历数组等。我尝试使用\\\\ (downArray) 移动到头部数组,然后:->-遍历数组,然后--\\ (downField) 不可用(至少 IntelliJ 不这么认为)。 So the question is how do i:所以问题是我该怎么做:

  • navigate to the array导航到数组
  • iterate through the array (and know when I'm done)遍历数组(并知道我什么时候完成)
  • extract string, integer etc. values for each field - jdecode[String] ?为每个字段提取字符串、整数等值 - jdecode[String] ? as[String] ? as[String]

The easiest way to do this is to define a codec for MyType .最简单的方法是为MyType定义一个编解码器。 The compiler will then happily construct a decoder for List[MyType] , etc. I'll use a plain class here (not a case class) to make it clear what's happening:然后编译器会很高兴地为List[MyType]等构造一个解码器。我将在这里使用一个普通类(不是案例类)来清楚地说明发生了什么:

class MyType(val name: String, val tpe: String, val size: Int)

import argonaut._, Argonaut._

implicit def MyTypeCodec: CodecJson[MyType] = codec3(
  (name: String, tpe: String, size: Int) => new MyType(name, tpe, size),
  (myType: MyType) => (myType.name, myType.tpe, myType.size)
)("name", "type", "size")

codec3 takes two parameter lists. codec3采用两个参数列表。 The first has two parameters, which allow you to tell how to create an instance of MyType from a Tuple3 and vice versa.第一个有两个参数,它们允许您告诉如何从Tuple3创建MyType的实例,反之亦然。 The second parameter list lets you specify the names of the fields.第二个参数列表允许您指定字段的名称。

Now you can just write something like the following (if json is your string):现在您可以编写如下内容(如果json是您的字符串):

Parse.decodeValidation[List[MyType]](json)

And you're done.你已经完成了。

Since you don't need to encode and are only looking at decoding, you can do as suggested by Travis, but by implementing another implicit: MyTypeDecodeJson由于您不需要编码并且只查看解码,因此您可以按照 Travis 的建议进行操作,但是通过实现另一个隐式:MyTypeDecodeJson

implicit def MyTypeDecodeJson: DecodeJson[MyType] = DecodeJson(
    raw => for {
    name     <- raw.get[String]("name")
    type     <- raw.get[String]("type")
    size     <- raw.get[Int]("size")
  } yield MyType(name, type, size))

Then to parse your list:然后解析您的列表:

Parse.decodeValidation[List[MyType]](jsonString)

Assuming MyType is a case class, the following works too:假设MyType是一个案例类,以下也适用:

case class MyType(name: String, type: String, size: Int)

object MyType {
    implicit val createCodecJson: CodecJson[MyType] = CodecJson.casecodec3(apply, unapply)(
        "name",
        "type",
        "size"
    )
}

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

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