1

my json looks like this.

[
  {"name": "AABC Register Ltd (Architects accredited in building conservation), with effect from the 2016 to 2017 tax year"},
  {"name": "Academic and Research Surgery Society of"},
  {"name": "Academic Gaming and Simulation in Education and Training Society for"},
  {"name": "Academic Primary Care Society for"}
]

and the code I use to parse this and add it to mongoDB is this

val sourceOrganisations: JsValue = Json.parse(getClass.getResourceAsStream("/json/ApprovedOrganisations.json"))

val organisations: Seq[String] = (sourceOrganisations.as[JsArray] \\ "name").map(jsval => jsval.toString())

println(organisations)

organisations.foreach(organisation => this.insert(Organisation(organisation)))

when querying mongo i get

{ "_id" : ObjectId("5c3dcf309770222486f50b4a"), "name" : "\"Accounting Association American\"" }

but i want this

{ "_id" : ObjectId("5c3dcf309770222486f50b4a"), "name" : "Accounting Association American" }

I have tried looking at why there might be extra quotes but can't find the reason

Akceptor
  • 1,914
  • 3
  • 26
  • 31

3 Answers3

1

The problem is because you are doing a toString on JsValue.

When you do a toString on a JsValue which is a JsString you get a String which has the value "value_inside_JsString"

val jsValue: JsValue = JsString("a")
val extraQuotedString = "[[" + jsValue.toString() + "]]"
// extraQuotedString: String = [["a"]]

The correct way is to first cast it to JsString and the getting its value by .value.

val correctString = "[[" + jsValue.as[JsString].value + "]]"
// correctString: String = [[a]]

So,

val json = Json.parse(jsonString)

val organizationsAsJsValues = json match {
  case jsArray: JsArray => jsArray \\ "name"
  case _ => Seq.empty[JsValue]
}

val organizationAsNames = organizationsAsJsValues.flatMap({
  case jsString: JsString => Some(jsString.value)
  case _ => None
})

val organizations = organizationAsNames.map(name => Organization(name))
sarveshseri
  • 13,738
  • 28
  • 47
  • You can do `as[String]` directly. But even better to make a case class for the whole structure and do `val myData = Json.parse(jsonString).as[MyStructure]`. – Thilo Jan 15 '19 at 13:14
  • 1
    @Thilo yes, but that comes after basic understanding of what is actually going on because use of "macro" generated `Reader` and `Writer` hides the whole logical flow. – sarveshseri Jan 15 '19 at 13:35
  • True, those are a bit gnarly. – Thilo Jan 15 '19 at 23:40
0
val organisations: Seq[String] = (sourceOrganisations.as[JsArray] \\ "name").map(jsval => jsval.toString().replaceAll("\"",""))

added replaceAll("\"","") to line to fix it. have no clue why it added the qoutes though

  • It added the quotes, because you asked it to. `jsval.toString` produces a String with the JSON encoding of `jsval`. – Thilo Jan 15 '19 at 13:12
0
jsval => jsval.toString()

This will give you the JSON representation of jsval. If that was a JsString, it will be the double quoted (and potentially escaped) text content.

You probably want to parse the JSON into a case class (sourceOrganisation = Json.parse(something).as[TheCaseClass]). That way, you can also avoid doing the manual parsing with jsArray \\ "name"

Or at least the final extract the String from the final jsval (if you know that it's a JsString, you could do jsval.as[String]).

Thilo
  • 257,207
  • 101
  • 511
  • 656