Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse JSON array using Scala Argonaut

I'm using Scala & Argonaut, trying to parse the following 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.

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). 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]? as[String]?
like image 226
Gilbert Avatar asked Mar 18 '14 15:03

Gilbert


People also ask

How to parse JSON data into an array of Scala objects?

This is Recipe 15.4, “How to parse JSON data into an array of Scala objects.” You have a JSON string that represents an array of objects, and you need to deserialize it into objects you can use in your Scala application. Use a combination of methods from the Lift-JSON library.

How do I deserialize a JSON Schema in Scala?

In comes Argonaut, a Scala JSON parsing library that enables you to deserialize directly into case classes. Just define your schema, represent it in case classes, and boom you’re done. No casting objects, no traversing nested fields, nothing. It’s a thing of beauty.

What is Argonaut and how do I use it?

In comes Argonaut, a Scala JSON parsing library that enables you to deserialize directly into case classes. Just define your schema, represent it in case classes, and boom you’re done.


1 Answers

The easiest way to do this is to define a codec for 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:

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. The first has two parameters, which allow you to tell how to create an instance of MyType from a Tuple3 and vice versa. 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):

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

And you're done.

like image 146
Travis Brown Avatar answered Sep 21 '22 20:09

Travis Brown