2

I've got the following JSON structure and I can't find a good way to parse it in Scala (I'm using circe BTW):

{
  "name": "xx",
  "args": [
    {"name":"xy", "args": []},
    [
      {"name":"xy", "args": []},
      {"name":"xy", "args": [[]]}
    ],
    [
      [
        {"name":"xy", "args": [{"name":"xy", "args": []}]}
      ]
    ]
  ]
}

Basically, it's a recursive structure that can contain either object, or list of objects, or list of lists, or list of lists of lists... or objects and lists.

How can I handle that? I'm thinking about some recursive types but I'm not sure about that.

2
  • Is that a valid JSON? Commented Nov 30, 2021 at 18:43
  • 1
    @GaëlJ yes it is. - Well, it has a trailing comma at line 13 but other than that is valid. Commented Nov 30, 2021 at 18:45

1 Answer 1

3

You need to model that as an ADT and derive a custom Decoder like this:

import io.circe.{Decoder, DecodingFailure, parser}
import io.circe.generic.semiauto.deriveDecoder

sealed trait Arg
object Arg {
  final case class OneArg(name: String, args: List[Arg]) extends Arg
  final case class MultipleArgs(args: List[Arg]) extends Arg
  
  private implicit final val OneArgDecoder: Decoder[OneArg] = deriveDecoder
  
  implicit final val ArgDecoer: Decoder[Arg] =
    Decoder.instance[Arg] { cursor =>
      cursor.focus match {
        case Some(json) =>
          // Here you may also ask if it is an array before to attempt to get it as a List[arg], and if not then provide a custom failure.
          if (json.isObject) json.as[OneArg]
          else json.as[List[Arg]].map(MultipleArgs)
        
        case None =>
          Left(DecodingFailure("Empty cursor", cursor.history))
      }
    }
}

Which can be used to decode your JSON: https://scastie.scala-lang.org/BalmungSan/W0lLBYRzTIS3PC4E5i0wXA/26

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.