java - GSON - Deserialize primitive array -
consider simple json:
{ "test": [ 0, 3 ] } now want deserialize in simple int array use custom deserializer:
class arraydeserializer implements jsondeserializer<int[]> { @override public int[] deserialize(jsonelement json, type typeoft, jsondeserializationcontext context) throws jsonparseexception { return context.deserialize(json.getasjsonobject().getasjsonarray("test"), int[].class); } } and then:
gson gson = new gsonbuilder().registertypeadapter(int[].class, new arraydeserializer()).create(); int[] arr = gson.fromjson(json, int[].class); which throws:
exception in thread "main" com.google.gson.jsonsyntaxexception: java.lang.illegalstateexception: not json object: [0,3] however when this:
class arraydeserializer implements jsondeserializer<int[]> { private static final gson gson = new gson(); @override public int[] deserialize(jsonelement json, type typeoft, jsondeserializationcontext context) throws jsonparseexception { return gson.fromjson(json.getasjsonobject().getasjsonarray("test"), int[].class); } } it works , expected output. why?
let's rewrite arraydeserializer in equivalent form more expressive
class arraydeserializer implements jsondeserializer<int[]> { @override public int[] deserialize(jsonelement json, type typeoft, jsondeserializationcontext context) throws jsonparseexception { jsonarray jsonarray = json.getasjsonobject().getasjsonarray("test"); return context.deserialize(jsonarray, int[].class); } } the jsondeserializationcontext#deserialize javadoc states
invokes default deserialization on specified object. should never invoked on element received parameter of
jsondeserializer.deserialize(jsonelement, type, jsondeserializationcontext)method. doing result in infinite loop sincegsonin-turn call custom deserializer again.
so, if had worked, you'd more have stackoverflow on hands.
so why didn't work?
you called (in pseudo-code)
deserialize {test:[0,3]} int[] // --> gson finds arraydeserializer mapped int[] take given json object (ok), extract 'test' json array (ok) deserialize [0,3] int[] // --> gson finds arraydeserializer mapped int[] take given json object (fail) this last time recurred, json in form of json array arraydeserializer expecting json object.
in second attempt
return gson.fromjson(json.getasjsonobject().getasjsonarray("test"), int[].class); you're again extracting 'test' json array , feeding new gson instance on haven't registered arraydeserializer. in effect, you're invoking
new gson().fromjson("[0,3]", int[].class); which supported out of box , return int[] 2 elements 0 , 3, expected.
there simpler solutions.
define simple pojo type
class pojo { private int[] test; public int[] gettest() { return test; } public void settest(int[] test) { this.test = test; } } and deserialize it
pojo pojo = new gson().fromjson(json, pojo.class); int[] arr = pojo.gettest(); or
gson gson = new gson(); jsonarray jsonarray = gson.tojsontree(json).getasjsonobject().get("test").getasjsonarray(); int[] arr = gson.fromjson(jsonarray, int[].class);
Comments
Post a Comment