skip to Main Content

do you guys know how to parse an array of json objects but without square brackets

{ "jsonValue1": "val1", "jsonValue2": [1, 1, 2, 2]}
{ "jsonValue1": "val1", "jsonValue2": [1, 1, 2, 2]}
{ "jsonValue1": "val1", "jsonValue2": [1, 1, 2, 2]}

to a List[MyScalaType]

case class MyScalaType(jsonValue1: String, jsonValue2: List[Int])

regular parsing to such List returns: error Malformed message body: Invalid JSON

2

Answers


  1. Chosen as BEST ANSWER

    well, thanks to Luis Miguel Mejía Suárez with "io.circe" %% "circe-fs2" i was able to parse such json

    here is short overview. i'm using http4s client

    client.get(uri)(
       _.bodyText
        .through(stringStreamParser)
        .through(decoder[F, MyScalaType])
        .compile
        .toList
    )
    

  2. For example you can split the string into lines and transform the string into a valid json string before parsing

    import io.circe.{Decoder, Json}
    import io.circe.parser.{decode, parse}
    import io.circe.generic.semiauto
    
    case class MyScalaType(jsonValue1: String, jsonValue2: List[Int])
    object MyScalaType {
      implicit val dec: Decoder[MyScalaType] = semiauto.deriveDecoder
    }
    
    val str =
      """
        { "jsonValue1": "val1", "jsonValue2": [1, 1, 2, 2]}
        { "jsonValue1": "val1", "jsonValue2": [1, 1, 2, 2]}
        { "jsonValue1": "val1", "jsonValue2": [1, 1, 2, 2]}
      """
    
    val lines = str.linesIterator.filter(_.trim.nonEmpty).toList
    
    val str1 = lines.mkString("[", ",", "]")
    
    val res = parse(str1)
    res.map(_.noSpaces)
    // Right([{"jsonValue1":"val1","jsonValue2":[1,1,2,2]},{"jsonValue1":"val1","jsonValue2":[1,1,2,2]},{"jsonValue1":"val1","jsonValue2":[1,1,2,2]}])
    res.flatMap(_.as[List[MyScalaType]])
    // Right(List(MyScalaType(val1,List(1, 1, 2, 2)), MyScalaType(val1,List(1, 1, 2, 2)), MyScalaType(val1,List(1, 1, 2, 2))))
    decode[List[MyScalaType]](str1)
    // Right(List(MyScalaType(val1,List(1, 1, 2, 2)), MyScalaType(val1,List(1, 1, 2, 2)), MyScalaType(val1,List(1, 1, 2, 2))))
    

    Or you can split the string into lines and parse every line into json

    import cats.syntax.traverse._
    
    val res = lines.traverse(parse).map(Json.arr)
    res.map(_.noSpaces)
    // Right([{"jsonValue1":"val1","jsonValue2":[1,1,2,2]},{"jsonValue1":"val1","jsonValue2":[1,1,2,2]},{"jsonValue1":"val1","jsonValue2":[1,1,2,2]}])
    res.flatMap(_.as[List[MyScalaType]])
    // Right(List(MyScalaType(val1,List(1, 1, 2, 2)), MyScalaType(val1,List(1, 1, 2, 2)), MyScalaType(val1,List(1, 1, 2, 2))))
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search