2

I'm trying to make a transformation to every object in an array in my JSON.

The JSON looks something like this:

{
  "foos": [
    {
      "urls": ["www.google.com", "www.google.com", "www.stackoverflow.com"]
    },
    {
      "urls": ["www.facebook.com"]
    },
    ...
  ]
}

I'm trying to remove duplicates from the urls array.

I've tried using something like this:

(__ \\ 'urls).json.update(Reads.of[JsArray].map(scopes => JsArray(scopes.value.distinct)))

But keep getting an error about error.path.result.multiple.

I can't seem to find a way to make the change to everything inside of a JSON array.

Also, I can't used case classes here because there are unknown fields on some of the data that I don't want to lose when converting to a case class.

Tomer Shetah
  • 7,646
  • 6
  • 20
  • 32
Billzabob
  • 33
  • 3

1 Answers1

0

In order to resolve that, we need to define 2 transformers. One acting on the internal object, to remove duplicates, and the other, to aggregate all objects.

The first one is:

val distinctTransformer = (__ \ "urls").json
  .update(__.read[JsArray].map{o => {
    JsArray(o.value.distinct)
  }})

The other one is:

val jsonTransformer = (__ \ "foos").json
  .update(__.read[JsArray].map(arr => {
    JsArray(arr.value.map(_.transform(distinctTransformer))
      .filter(_.isSuccess) // Error handling should be added here
      .map(_.get)
    )
  }))

Then the usage is:

val json = Json.parse(jsonString)
json.transform(jsonTransformer) match {
  case JsSuccess(value, _) =>
    println(value)
  case JsError(errors) =>
    println(errors)
}

Code run at Scastie.

Tomer Shetah
  • 7,646
  • 6
  • 20
  • 32