1

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

isijara
  • 155
  • 2
  • 9

2 Answers2

2

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.

BitParser
  • 3,748
  • 26
  • 42
  • I was trying to only use the streaming api, but it seems it will have to be this way, thanks @TGO – isijara Jan 16 '18 at 18:27
1

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

Cedric Beust
  • 15,480
  • 2
  • 55
  • 55
  • That would be a nested `beginObject()`? If it is, do I have to start a new JsonReader? I am facing the same problem, can you please show how to do it, based onthe example in the original question? – Ali_Habeeb Nov 02 '20 at 19:28