Parse \n separated json with circe

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

Upvotes: 1

Views: 305

Answers (2)

Dmytro Mitin
Dmytro Mitin

Reputation: 51658

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))))

Upvotes: 1

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
)

Upvotes: 3

Related Questions