isijara
isijara

Reputation: 155

Klaxon: Expected a name but got LEFT_BRACE

How can I read a "complex" json using Klaxon? I'm trying to use klaxon's stream api as documentation say .

I'm using the beginObject method. If I use a json as given in the example everything is fine

val objectString = """{
 "name" : "Joe",
 "age" : 23,
 "flag" : true,
 "array" : [1, 3],
 "obj1" : { "a" : 1, "b" : 2 }
}"""

But if I try to parse a json with a nested object as the following example I get the following error: "Expected a name but got LEFT_BRACE"

val objectString = """{
 "name" : "Joe",
 "age" : 23,
 "flag" : true,
 "array" : [1, 3],
 "obj1" : { 
             "hello": { "a" : 1, "b" : 2 } 
          }
}"""

I don't see any reported issues in the github repo, so I wonder if there is a way to get this working.

cheers

Upvotes: 1

Views: 594

Answers (2)

Cedric Beust
Cedric Beust

Reputation: 15608

With the Streaming API, you are in charge of parsing objects and arrays yourself, so when you encounter the name "obj1", you need to start a new beginObject() { ... } and parse that object there.

The documentation that you linked does exactly that:

while (reader.hasNext()) { val readName = reader.nextName() when (readName) { "name" -> name = reader.nextString() "age" -> age = reader.nextInt() "flag" -> flag = reader.nextBoolean() "array" -> array = reader.nextArray() "obj1" -> obj1 = reader.nextObject()

Upvotes: 1

BitParser
BitParser

Reputation: 3968

Ok so I checked out the source, and it seems that nextObject() assumes that you are dealing with a simple key value object, where values are not objects.

Anyway, there is another way to parse a JSON of the format you specified, like below:

val objectString = """{
         "name" : "Joe",
         "age" : 23,
         "flag" : true,
         "array" : [1, 2, 3],
         "obj1" : { "hello": {"a" : 1, "b" : 2 } }
    }"""

class ABObj(val a: Int, val b: Int)

class HelloObj(val hello: ABObj)

class Obj(val name: String, val age: Int, val flag: Boolean, val array: List<Any>, val obj1: HelloObj)


val r = Klaxon().parse<Obj>(objectString)

// r is your parsed object
print(r!!.name) // prints Joe
print(r!!.array) // prints [1, 2, 3]

The classes I created are like below:

ABObj represents this JSON:

{"a": 1, "b": 2}

HelloObj represents this JSON:

{"hello": {"a": 1, "b": 2}}

And finally, Obj refers to the top level object.

Hope this helps.

Upvotes: 2

Related Questions