Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I know this is a fairly old question, but I was searching for a solution to generically deserialize nested JSON to a <code>Map&lt;String, Object&gt;</code>, and found nothing.</p> <p>The way my yaml deserializer works, it defaults JSON objects to <code>Map&lt;String, Object&gt;</code> when you don't specify a type, but gson doesn't seem to do this. Luckily you can accomplish it with a custom deserializer.</p> <p>I used the following deserializer to naturally deserialize anything, defaulting <code>JsonObject</code>s to <code>Map&lt;String, Object&gt;</code> and <code>JsonArray</code>s to <code>Object[]</code>s, where all the children are similarly deserialized.</p> <pre><code>private static class NaturalDeserializer implements JsonDeserializer&lt;Object&gt; { public Object deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) { if(json.isJsonNull()) return null; else if(json.isJsonPrimitive()) return handlePrimitive(json.getAsJsonPrimitive()); else if(json.isJsonArray()) return handleArray(json.getAsJsonArray(), context); else return handleObject(json.getAsJsonObject(), context); } private Object handlePrimitive(JsonPrimitive json) { if(json.isBoolean()) return json.getAsBoolean(); else if(json.isString()) return json.getAsString(); else { BigDecimal bigDec = json.getAsBigDecimal(); // Find out if it is an int type try { bigDec.toBigIntegerExact(); try { return bigDec.intValueExact(); } catch(ArithmeticException e) {} return bigDec.longValue(); } catch(ArithmeticException e) {} // Just return it as a double return bigDec.doubleValue(); } } private Object handleArray(JsonArray json, JsonDeserializationContext context) { Object[] array = new Object[json.size()]; for(int i = 0; i &lt; array.length; i++) array[i] = context.deserialize(json.get(i), Object.class); return array; } private Object handleObject(JsonObject json, JsonDeserializationContext context) { Map&lt;String, Object&gt; map = new HashMap&lt;String, Object&gt;(); for(Map.Entry&lt;String, JsonElement&gt; entry : json.entrySet()) map.put(entry.getKey(), context.deserialize(entry.getValue(), Object.class)); return map; } } </code></pre> <p>The messiness inside the <code>handlePrimitive</code> method is for making sure you only ever get a Double or an Integer or a Long, and probably could be better, or at least simplified if you're okay with getting BigDecimals, which I believe is the default.</p> <p>You can register this adapter like:</p> <pre><code>GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(Object.class, new NaturalDeserializer()); Gson gson = gsonBuilder.create(); </code></pre> <p>And then call it like:</p> <pre><code>Object natural = gson.fromJson(source, Object.class); </code></pre> <p>I'm not sure why this is not the default behavior in gson, since it is in most other semi-structured serialization libraries...</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload