Reputation: 5648
I am trying to use the default Json facilities to output an object as JSON. But unfortunately, the object in question actually has cycles in it. I need the JSON to either output #ref
or simply prune it.
I have been working with the JsonGenerator and trying to define a custom converter that merely stops following an object serialization when it discovers something it has already encountered. I can't use a classic hashing structure because this would have the same problem: hence the use of an IdentityHashMap
. Because I am basically trying to export a complicated structure from Jenkins I don't have the luxury knowing what field I can exclude (in fact, I am trying to determine what fields are available).
NullPointerException
because apparently it doesn't handle null values (that makes no sense because that's a pretty common case). excludeNulls()
to the builder; same result. If the question isn't obvious, then it's this: How do you take the below map structure and get it to output JSON; pruning cycles if needed but I don't really care how.
import groovy.json.JsonGenerator
import groovy.json.JsonGenerator.Converter
def loop = [
loop: [:]
]
def thing = [
foo:'hello',
baz: [
bat:loop
]
]
loop.loop = thing
new JsonGenerator.Options().addConverter(new Converter() {
private seen = [:] as IdentityHashMap
@Override
boolean handles(Class<?> aClass) {
true
}
@Override
Object convert(Object o, String s) {
if(! (seen[o]) && o){
seen[o] = 'seen + o'
o
}
}
}).build().toJson(thing).with { println(it)}
Upvotes: 0
Views: 147
Reputation: 28564
seems JsonGenerator
thrown NPE
when Converter.convert(v,key)
returns null on original non-null value...
import groovy.json.JsonGenerator
import groovy.json.JsonGenerator.Converter
def loop = [
loop: [:]
]
def thing = [
foo:'hello',
baz: [
bat:loop
],
nnn: null
]
loop.loop = thing
new JsonGenerator.Options().addConverter(new Converter() {
private seen = [:] as IdentityHashMap
@Override
boolean handles(Class<?> aClass) {
true
}
@Override
Object convert(Object o, String key) {
if(o!=null){
if( seen[o] ){
//o = null //null instead of '<seen>' throws NPE
o = '<seen>'
}else{
seen.put(o,true)
}
}
return o
}
}).build().toJson(thing).with { println(it)}
Upvotes: 1