I want to convert below json array to java hashmap using jackson and iterate the values like below:
Need output like this:
key Value
1 sql
2 android
3 mvc
JSON Sample:
enter code here
{
"menu": [
{
"1": "sql",
"2": "android",
"3": "mvc"
}
]
}
It would be really appreciated if someone can share the code to achieve this.
Thanks for your help!
Here is a solution that reveals the idea:
public class JacksonSerializer {
public static final String INPUT = "{\n" +
" \"menu\": [\n" +
" {\n" +
" \"1\": \"sql\",\n" +
" \"2\": \"android\",\n" +
" \"3\": \"mvc\"\n" +
" }\n" +
" ]\n" +
"}";
public static class MenuItems {
Map<String, String> menu = Maps.newHashMap();
}
public static class MenuItemsDeserializer extends JsonDeserializer<MenuItems> {
#Override
public MenuItems deserialize(org.codehaus.jackson.JsonParser jsonParser,
DeserializationContext deserializationContext)
throws IOException, JsonProcessingException {
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
final JsonNode elems = node.getElements().next().getElements().next();
final Map<String, String> map = Maps.newHashMap();
final Iterator<Map.Entry<String, JsonNode>> it = elems.getFields();
while (it.hasNext()) {
final Map.Entry<String, JsonNode> entry = it.next();
map.put(entry.getKey(), entry.getValue().asText());
}
final MenuItems menuItems = new MenuItems();
menuItems.menu = map;
return menuItems;
}
}
public static void main(final String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule("SimpleModule",
new Version(1,0,0,null));
module.addDeserializer(MenuItems.class, new MenuItemsDeserializer());
mapper.registerModule(module);
MenuItems menuItems = mapper.readValue(INPUT, MenuItems.class);
}
}
Related
So I have a Map<String, ArrayList> parentToChild and want to create basically a "Family Tree" or nested hierarchy. Below is an example of the map but there could be more children at each level e.g. (Claire could have Matt and Bruce as children):
David -> [Claire]
Claire -> [Matt]
Matt -> [Sean, Terry]
I know the root of the tree should be David for the above example and it will only have one root.
Example output
{
"David": {
"Claire": {
"Matt": {
"Sean": {},
"Terry": {}
}
}
}
}
I've tried few things but genuinely stumped.
EDIT: Code tried so far
public Set<Tree> transform(Map<String, ArrayList<String>> input) {
Set<String> roots = new HashSet<String>(input.keySet());
Map<String, Tree> map = new HashMap<String, Tree>();
for (Map.Entry<String, ArrayList<String>> entry : input.entrySet()) {
String key = entry.getKey();
List<String> childKeys = entry.getValue();
Tree tree = map.get(key);
if (tree == null) {
tree = new Tree(key);
map.put(key, tree);
}
for (String childKey : childKeys) {
roots.remove(childKey);
Tree child = map.get(childKey);
if (child == null) {
child = new Tree(childKey);
map.put(childKey, child);
}
tree.addChild(child);
}
}
Set<Tree> res = new HashSet<Tree>(roots.size());
for (String key : roots) {
res.add(map.get(key));
}
return res;
}
Tree class:
public class Tree {
private String key;
private Tree child;
public Tree(String key){
this.key = key;
}
public void addChild(Tree child){
this.child = child;
}
}
The issue is when I use this code the output (What is in the set after debugging/printing) I get is
David:
Claire:
Matt:
Terry:
You could use a Map<String,Object>:
private static final Gson GSON = new GsonBuilder()
.setPrettyPrinting()
.create();
public static void main(String[] args) {
Map<String, List<String>> input = new HashMap<>();
input.put("David", Arrays.asList("Claire"));
input.put("Claire", Arrays.asList("Matt"));
input.put("Matt", Arrays.asList("Sean", "Terry"));
Map<String,Object> result = new HashMap<>();
convert(input, "David", result);
GSON.toJson(result, System.out);
}
private static void convert(Map<String, List<String>> input, String root,
Map<String,Object> result) {
if (!result.containsKey(root)) {
Map<String,Object> rootObj = new HashMap<>();
result.put(root, rootObj);
List<String> children = input.get(root);
if (children != null) {
for (String child: children) {
convert(input, child, rootObj);
}
}
}
}
Output:
{
"David": {
"Claire": {
"Matt": {
"Terry": {},
"Sean": {}
}
}
}
}
In the Java world you have access to Saxon 9.8 or later HE where XPath 3.1 or XQuery 3.1 or XSLT 3.0 all have support for representing your initial map as an XdmMap and processing them, for instance with XQuery:
declare namespace map = "http://www.w3.org/2005/xpath-functions/map";
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:method 'json';
declare option output:indent 'yes';
declare variable $map as map(xs:string, array(xs:string)) external := map {
'David' : [ 'Claire' ],
'Claire' : [ 'Matt' ],
'Matt' : [ 'Sean', 'Terry' ]
};
declare variable $root as xs:string external := 'David';
declare function local:create-tree($map as map(xs:string, array(xs:string)), $children as xs:string*) as map(*) {
map:merge($children ! map { . : local:create-tree($map, $map(.)) })
};
local:create-tree($map, $root)
https://xqueryfiddle.liberty-development.net/3Nzd8bV
A simple Java example to run this with Saxon 10 HE (its API documentation is at http://saxonica.com/html/documentation/using-xquery/api-query/s9api-query.html), passing a Java Map to the XQuery (inserted inline as a string but could of course be loaded from a file instead) is:
import java.util.HashMap;
import java.util.Map;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XQueryCompiler;
import net.sf.saxon.s9api.XQueryEvaluator;
import net.sf.saxon.s9api.XQueryExecutable;
import net.sf.saxon.s9api.XdmMap;
public class SaxonJavaMapToNestedJSONObject {
public static void main(String[] args) throws SaxonApiException {
Map<String, String[]> map = new HashMap<>();
map.put("David", new String[] { "Claire" });
map.put("Claire", new String[] { "Matt" });
map.put("Matt", new String[] { "Sean", "Terry" });
Processor processor = new Processor(true);
XQueryCompiler compiler = processor.newXQueryCompiler();
XQueryExecutable executable = compiler.compile("declare namespace map = \"http://www.w3.org/2005/xpath-functions/map\";\n" +
"\n" +
"declare namespace output = \"http://www.w3.org/2010/xslt-xquery-serialization\";\n" +
"\n" +
"declare option output:method 'json';\n" +
"declare option output:indent 'yes';\n" +
"\n" +
"declare variable $map as map(xs:string, array(xs:string)) external;\n" +
"\n" +
"declare variable $root as xs:string external := 'David';\n" +
"\n" +
"declare function local:create-tree($map as map(xs:string, array(xs:string)), $children as xs:string*) as map(*) {\n" +
" map:merge($children ! map { . : local:create-tree($map, $map(.)) })\n" +
"};\n" +
"\n" +
"local:create-tree($map, $root)");
XQueryEvaluator evaluator = executable.load();
evaluator.setExternalVariable(new QName("map"), XdmMap.makeMap(map));
evaluator.run(processor.newSerializer(System.out));
}
}
Of course you could set the root variable as well from Java: evaluator.setExternalVariable(new QName("root"), new XdmAtomicValue("David"));
Hey I have also problem here is my Json
[
{
"aimid": "12345"
},
{
"aimid": "333674"
},
{
"aimid": [
"4568999",
"6789345"
]
}]
and This is my Pojo class:-
#JsonProperty("aimid")
private String aimid;
public String getAimid() {
return aimid;
}
public void setAimid(String aimid) {
this.aimid = aimid;
}
I want to store aimid in pojo . When i am writing like above in my application i am getting error.
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_ARRAY token.
From my understanding i am getting error because of Array element so anyone can suggest me how i can capture both thing if it is coming as String or It is coming as a Array String
The challenge is that in some cases "aimid" is a string value but in another case it is an array.
If you have control over the structure of the JSON then update the structure so that each element of the root array has ONE of the following structures:
String
{
"aimid": "333674"
}
OR array
{
"aimid": [
"4568999",
"6789345"
]
}
If you do not have control of the structure of the data you will need to parse it yourself and process it into your POJO.
Please see these 3 code examples that should illustrate how you can go about this approaches. :
public class MyPojo {
private List<String> aimid;
#JsonProperty("aimid")
public List<String> getAimid() {
return aimid;
}
#JsonProperty("aimid_array")
public void setAimid(final List<String> aimid) {
this.aimid = aimid;
}
#JsonProperty("aimid")
public void setAimid(final String aimid) {
this.aimid = Arrays.asList(aimid);
}
}
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.node.*;
import java.io.IOException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.junit.Test;
public class UnitTest {
private static final Logger LOGGER = Logger.getLogger(UnitTest.class.getName());
public UnitTest() {
}
#Test
public void testOneAimId() throws IOException {
final String json = "[\n"
+ "{\n"
+ " \"aimid\": \"12345\"\n"
+ "},\n"
+ "{\n"
+ " \"aimid\": \"333674\"\n"
+ "}]";
final List<MyPojo> result = new ObjectMapper().readValue(json, new TypeReference<List<MyPojo>>() {
});
log(Level.SEVERE, LOGGER, "testOneAimId", result);
}
#Test
public void testListAimIds() throws IOException {
final String json = "[\n"
+ "{\n"
+ " \"aimid_array\": [\n" // HERE WE HAVE CHANGED THE JSON PROP NAME
+ " \"4568999\",\n"
+ " \"6789345\"\n"
+ " ]\n"
+ "}]";
final List<MyPojo> result = new ObjectMapper().readValue(json, new TypeReference<List<MyPojo>>() {
});
log(Level.SEVERE, LOGGER, "testListAimIds", result);
}
#Test
public void testMixed() throws IOException {
final String json = "[\n"
+ "{\n"
+ " \"aimid\": \"12345\"\n"
+ "},\n"
+ "{\n"
+ " \"aimid\": \"333674\"\n"
+ "},\n"
+ "{\n"
+ " \"aimid_array\": [\n" // HERE WE HAVE CHANGED THE JSON PROP NAME
+ " \"4568999\",\n"
+ " \"6789345\"\n"
+ " ]\n"
+ "}]";
final List<MyPojo> result = new ObjectMapper().readValue(json, new TypeReference<List<MyPojo>>() {
});
log(Level.SEVERE, LOGGER, "testMixed", result);
}
#Test
public void testMixed2() throws IOException {
final String json = "[\n"
+ "{\n"
+ " \"aimid\": \"12345\"\n"
+ "},\n"
+ "{\n"
+ " \"aimid\": \"333674\"\n"
+ "},\n"
+ "{\n"
+ " \"aimid\": [\n"
+ " \"4568999\",\n"
+ " \"6789345\"\n"
+ " ]\n"
+ "}]";
final JsonNode result = new ObjectMapper().readValue(json, JsonNode.class);
final ArrayList<String> arrayList = new ArrayList<>();
result.forEach((final JsonNode jsonNode) -> {
if (jsonNode.getNodeType() != JsonNodeType.OBJECT)
throw new IllegalArgumentException(jsonNode.toString());
final ObjectNode obj = (ObjectNode) jsonNode;
obj.forEach(o -> {
switch (o.getNodeType()) {
case ARRAY:
final ArrayNode array = (ArrayNode) o;
array.forEach(t -> arrayList.add(t.asText()));
break;
case STRING:
arrayList.add(o.asText());
break;
default:
throw new IllegalArgumentException(o.toString());
}
});
});
final MyPojo myPojo = new MyPojo();
myPojo.setAimid(arrayList);
log(Level.SEVERE, LOGGER, "myPojo", myPojo);
}
private void log(final Level level, final Logger logger, final String title, final Object obj) {
try {
if (title != null)
logger.log(level, title);
final ObjectWriter writer = new ObjectMapper().writerWithDefaultPrettyPrinter();
logger.log(level, obj == null ? "null" : writer.writeValueAsString(obj));
} catch (final JsonProcessingException ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
}
}
}
I am trying to write a generic code were a JSON array as below example can be converted to a map .
This is sample .
where parent element is menu
{"menu": {
"items": [
{"id": "Open"},
{"id": "OpenNew", "label": "Open New"},
{"id": "ZoomIn", "label": "Zoom In"},
{"id": "ZoomOut", "label": "Zoom Out"},
{"id": "Quality"},
{"id": "Pause"}
]
}}
to map having map values as :
menu.items_0.id=open
menu.items_1.id=OpenNew
menu.items_1.label=Open New
menu.items_2.id=ZoomIn
menu.items_2.label=Zoom In
menu.items_3.id=ZoomOut
menu.items_3.id=Zoom Out
menu.items_4.id=Quality
menu.items_5.id=Pause
For my answer you need these classes:
org.json.JSONArray;
org.json.JSONException;
org.json.JSONObject;
And I'm assuming a class like this:
public class menu{
private String id;
private String label;
}
To parse - I'm ignoring if it's a stream, file, etc -. However, it assumes you've manipulated your source to create a single long String object called myString.
JSONObject topLevel = new JSONObject( myString );
JSONObject itemsArray= topLevel.getJSONArray("items");
int tempID;
String tempLabel;
//Now go through all items in array.
for(int i =0; i < itemsArray.length(); i++){
tempID = itemsArray.getJSONObject(i).getString("id");
if(itemsArray.getJSONObject(i).has("label"))
tempLabel = itemsArray.getJSONObject(i).getString("label");
else
tempLabel = null;
//whatever action you need to take
menu = new menu( tempId, tempLabel);
}
This code here gets the job done. You can extract some methods, or refactor it a little, but it should do the trick.
public class Example {
public static void main(String[] args) {
String source = "{\"menu\": {\"items\": [{\"id\": \"Open\"},{\"id\": \"OpenNew\", \"label\": \"Open New\"}, " +
"{\"id\": \"ZoomIn\", \"label\": \"Zoom In\"},"
+ "{\"id\": \"ZoomOut\", \"label\": \"Zoom Out\"},{\"id\": \"Quality\"},{\"id\": \"Pause\"}"
+ "]}}";
JSONObject jsonObject = new JSONObject(source);
Map<String, Object> map = jsonObject.toMap();
Map<String, String> resultMap = new HashMap<>();
map
.entrySet()
.forEach(entry -> addToResult(entry, resultMap, "", ""));
System.out.println(resultMap);
}
private static void addToResult(Map.Entry<String, Object> entry, Map<String, String> resultMap, String fieldNameAcummulator, String index) {
Object value = entry.getValue();
if (!Map.class.isAssignableFrom(value.getClass()) && !List.class.isAssignableFrom(value.getClass())) {
resultMap.put(addToAccumulator(entry, fieldNameAcummulator, index), (String) value);
return;
}
if (Map.class.isAssignableFrom(value.getClass())) {
Map<String, Object> nestedMap = (HashMap<String, Object>) value;
nestedMap
.entrySet()
.forEach(nestedEntry -> addToResult(nestedEntry, resultMap, addToAccumulator(entry, fieldNameAcummulator, index), ""));
} else {
List<HashMap<String, Object>> hashMaps = (List<HashMap<String, Object>>) value;
IntStream.range(0, hashMaps.size())
.forEach(listIndex -> {
HashMap<String, Object> nestedMap = hashMaps.get(listIndex);
nestedMap.entrySet().forEach(nestedEntry -> addToResult(nestedEntry, resultMap, addToAccumulator(entry, fieldNameAcummulator, index), String.valueOf(listIndex)));
});
}
}
private static String addToAccumulator(Map.Entry<String, Object> entry, String fieldNameAcummulator, String index) {
return fieldNameAcummulator.isEmpty()
? entry.getKey()
: fieldNameAcummulator + getKeyValueWithIndex(entry, index);
}
private static String getKeyValueWithIndex(Map.Entry<String, Object> entry, String index) {
return index.isEmpty()
? ".".concat(entry.getKey())
: "_".concat(index).concat(".").concat(entry.getKey());
}
}
Feel free to ask if you have any questions regarding the implementation.
Hope it helps!
I have change some logic and it works fine after that.
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.json.JSONArray;
import org.json.JSONObject;
public class JsonToMapConvertor {
private static HashMap<String, Object> mapReturn = new HashMap<String, Object>();
public static JsonParser parser = new JsonParser();
public static void main(String[] args) throws Exception{
String json ="{\n" +
" \"glossary\": {\n" +
" \"title\": \"example glossary\",\n" +
" \"GlossDiv\": {\n" +
" \"title\": \"S\",\n" +
" \"GlossList\": {\n" +
" \"GlossEntry\": {\n" +
" \"ID\": \"SGML\",\n" +
" \"SortAs\": \"SGML\",\n" +
" \"GlossTerm\": \"Standard Generalized Markup Language\",\n" +
" \"Acronym\": \"SGML\",\n" +
" \"Abbrev\": \"ISO 8879:1986\",\n" +
" \"GlossDef\": {\n" +
" \"para\": \"A meta-markup language, used to create markup languages such as DocBook.\",\n" +
" \"GlossSeeAlso\": [\"GML\", \"XML\"]\n" +
" },\n" +
" \"GlossSee\": \"markup\"\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
HashMap<String, Object> map = createHashMapFromJsonString(json,"");
System.out.println("map size "+map.size());
for (Map.Entry<String, Object> entry : map.entrySet()) {
if(!entry.getValue().toString().contains("{"))
System.out.println(entry.getKey()+" : "+entry.getValue());
}
}
public static HashMap<String, Object> createHashMapFromJsonString(String json,String prefix) throws Exception{
if(json.startsWith("[",0)){
JSONArray jsonArray = new JSONArray(json);
for (int i = 0; i < jsonArray.length(); i++){
JSONObject jsonobject = jsonArray.getJSONObject(i);
createHashMapFromJsonString(jsonobject.toString(), prefix+"_"+i);
}
}
else{
JsonObject object = (JsonObject) parser.parse(json);
Set<Map.Entry<String, JsonElement>> set = object.entrySet();
Iterator<Map.Entry<String, JsonElement>> iterator = set.iterator();
while (iterator.hasNext()) {
Map.Entry<String, JsonElement> entry = iterator.next();
String key = entry.getKey();
if(prefix.length()!=0){
key = prefix + "."+key;
}
JsonElement value = entry.getValue();
if (null != value) {
if (!value.isJsonPrimitive()) {
if (value.isJsonObject()) {
mapReturn.put(key, createHashMapFromJsonString(value.toString(),key));
} else if (value.isJsonArray() && value.toString().contains(":")) {
List<HashMap<String, Object>> list = new ArrayList<>();
JsonArray array = value.getAsJsonArray();
if (null != array) {
for (JsonElement element : array) {
if (!element.isJsonPrimitive()) {
createHashMapFromJsonString(value.toString(),key);
}else{
list.add(createHashMapFromJsonString(value.toString(),key));
}
}
mapReturn.put(key, list);
}
} else if (value.isJsonArray() && !value.toString().contains(":")) {
mapReturn.put(key, value.getAsJsonArray());
}
} else {
mapReturn.put(key, value.getAsString());
}
}
}
}
return mapReturn;
}
}
Just another way of converting JSONObject as List of Map as Generic
public static List<Map<String, Object>> getJsonNode(String jsonContents, String nodeName)
throws JsonProcessingException, IOException, ParseException {
JSONParser parser = new JSONParser();
JSONObject json = (JSONObject) parser.parse(jsonContents);
Object o = json.get(nodeName);
List<Map<String, Object>> results = Lists.newArrayList();
if (o instanceof JSONObject) {
results.add((Map<String, Object>) o);
} else if (o instanceof JSONArray) {
List<Map<String, Object>> hashMaps = (List<Map<String, Object>>) o;
results.addAll((Collection<? extends Map<String, Object>>) hashMaps);
}
return results;
}
/**
* Driver
*
* #param args
* #throws IOException
* #throws ParseException
*/
public static void main(String[] args) throws IOException, ParseException {
String jsonInputFile = "temp/input.json";
String jsonContents = new String(Files.readAllBytes(Paths.get(jsonInputFile)));
List<Map<String, Object>> results = getJsonNode(jsonContents, "summary");
for (Map<String, Object> entry : results) {
System.out.println(entry);
}
///////////////////////////////////////
results = getJsonNode(jsonContents, "payWay");
for (Map<String, Object> entry : results) {
System.out.println(entry);
}
///////////////////////////////////////
results = getJsonNode(jsonContents, "sellerDetails");
for (Map<String, Object> entry : results) {
System.out.println(entry);
}
}
What's the best way to deserialize this Json object?
{
"key1" : "val1",
"key2" : "blank"
}
into a java hashmap, where the string blank is replaced with null?
{
"key1" : "val1",
"key2" : null
}
I am currently using Jackson for deserialization.
You will find part of the answer here.
You just need to manipulate the line inside the while loop:
Object value;
if (object.get(key).equals("blank")) {
value = "null";
} else {
value = object.get(key);
}
and make print out will give:
System.out.println(map.get("key1")); // returns val1
System.out.println(map.get("key2")); // returns null
You final code will look like this, and you might need to import the proper .jar files:
import com.orsoncharts.util.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import static com.sun.xml.internal.ws.binding.WebServiceFeatureList.toList;
public class JsonAnswerOne {
public static void main(String[] args) throws JSONException {
String input = "{\n" +
" \"key1\" : \"val1\",\n" +
" \"key2\" : \"blank\"\n" +
"}";
parse(input);
}
private static void parse(String input) throws JSONException {
JSONObject mainObject = new JSONObject(input);
Map<String, Object> map = jsonToMap(mainObject);
System.out.println(map.get("key1")); // returns val1
System.out.println(map.get("key2")); // returns null
}
private static Map<String, Object> jsonToMap(JSONObject json) throws JSONException {
Map<String, Object> retMap = new HashMap<String, Object>();
if (json != JSONObject.NULL) {
retMap = toMap(json);
}
return retMap;
}
private static Map<String, Object> toMap(JSONObject object) throws JSONException {
Map<String, Object> map = new HashMap<String, Object>();
Iterator<String> keysItr = object.keys();
while (keysItr.hasNext()) {
String key = keysItr.next();
Object value;
if (object.get(key).equals("blank")) {
value = "null";
} else {
value = object.get(key);
}
if (value instanceof JSONArray) {
value = toList((JSONArray) value);
} else if (value instanceof JSONObject) {
value = toMap((JSONObject) value);
}
map.put(key, value);
}
return map;
}
}
I tried this and ended up with this:
// use of the deserializer
String json = "{\"key1\":\"val1\",\"key2\":\"blank\"}";
ObjectMapper mapperMap = new ObjectMapper();
SimpleModule moduleMap = new SimpleModule();
moduleMap.addDeserializer(Map.class, new MapDeserializer());
mapperMap.registerModule(moduleMap);
Map map = mapperMap.readValue(json, Map.class);
// custom deserializer
public class MapDeserializer extends StdDeserializer<Map<String, String>> {
public MapDeserializer() {
this(null);
}
public MapDeserializer(Class<?> vc) {
super(vc);
}
#Override
public Map<String, String> deserialize(JsonParser jp, DeserializationContext context)
throws IOException {
// definitely not the best way but it works...
Map<String, String> map = new HashMap<>();
String[] keys = new String[] {"key1", "key2"};
JsonNode node = jp.getCodec().readTree(jp);
String value;
for (String key : keys) {
value = node.get(key).asText();
if (value.equals("blank")) {
value = null;
}
map.put(key, value);
}
return map;
}
}
Full example solution with an additional example to deserialize the JSON into another class:
https://gist.github.com/audacus/e70ce0f3cd4b17197d911769e05b237e
Say I'm building my GSON object like this
new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
and now I want to deserialize the following JSON
{
"MyMap" : {
"Key1" : "Foo",
"Key2" : "Bar"
}
}
into the following class (which is working just fine)
public class MapClass {
Map<String,String> myMap;
}
but I also would like the keys to be named "key1" and "key2". How would I go about this?
You can try in this way:
try {
JSONObject jObj = new JSONObject("{"
+ " \"MyMap\" : {"
+ " \"Key1\" : \"Foo\","
+ " \"Key2\" : \"Bar\""
+ " }"
+ "}"); // this parses the json
JSONObject jObjt = jObj.getJSONObject("MyMap");
//old version with out GSON
Map<String, String> map = new HashMap();
Iterator itr = jObjt.keys();
while (itr.hasNext()) {
String key = (String) itr.next();
String value = jObjt.getString(key);
map.put(key, value);
}
//desalinized one with GSON
Map<String, String> map1 = new Gson().fromJson(jObjt.toString(), HashMap.class);
for (String str : map1.keySet()) {
System.out.println("k:" + str + " v:" + map1.get(str));
}
} catch (JSONException ex) {
//log the error
}
FieldNamingPolicy is applied to fields of json value. It is not possible to apply this to maps' keys (a map which has key, value pairs) at json.
Easy solution:
After deserialization, iterate over your map and rename key names. i.e. Key1 to key1 and Key2 to key2.
Other solution:
Write a custom TypeAdapter which handles deserialization process and renames keys.
public class MapClassTypeAdapter extends TypeAdapter<MapClass> {
#Override
public MapClass read(JsonReader in) throws IOException {
final MapClass mapClassInstance = new MapClass();
mapClassInstance.myMap = new HashMap<String, String>();
in.beginObject();
if("myMap".equalsIgnoreCase(in.nextName())) {
in.beginObject();
while (in.hasNext()) {
String key = in.nextName();
// You want keys as camel case
String newKey = key.substring(0,1).toLowerCase() + key.substring(1);
String value = in.nextString();
mapClassInstance.myMap.put(newKey, value);
}
in.endObject();
}
in.endObject();
return mapClassInstance;
}
#Override
public void write(JsonWriter out, MapClass mapClass) throws IOException {
throw new RuntimeException("MapClassTypeAdapter.write method not implemented yet!");
}
}
Test Other solution:
String json = "{\"myMap\":{\"Key1\":\"Foo\",\"Key2\":\"Bar\"}}";
final GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(MapClass.class, new MapClassTypeAdapter());
final Gson gson = gsonBuilder.create();
MapClass mapClass = gson.fromJson(json, MapClass.class);