package de.jpaw.bonaparte.xml; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.adapters.XmlAdapter; public class XmlJsonAdapter extends XmlAdapter<XmlJsonAdapter.JSON, Map<String, Object>> { @XmlType(name="JSON", namespace="http://www.jpaw.de/schema/bonaparte.xsd") public static class JSON { public List<KVP> kvp; // key / value pairs } @XmlType(name="KVP", namespace="http://www.jpaw.de/schema/bonaparte.xsd") public static class KVP { public String key; public Double num; public List<Double> nums; public String value; public List<String> values; public Boolean bool; public List<Boolean> bools; public JSON obj; public List<JSON> objs; public Object any; public List<Object> anys; } private static Object firstNonNull(Object ... objs) { for (Object o : objs) if (o != null) return o; return null; } // utility method to unmarshal a nested list of JSON objects protected List<Map<String, Object>> unmarshal(List<JSON> entries) throws Exception { if (entries == null) return null; List<Map<String, Object>> result = new ArrayList<Map<String, Object>>(entries.size()); for (JSON e : entries) result.add(unmarshal(e)); return result; } @Override public Map<String, Object> unmarshal(JSON entries) throws Exception { if (entries == null || entries.kvp == null) return null; Map<String, Object> map = new HashMap<String, Object>(2 * entries.kvp.size()); for(KVP kvp : entries.kvp) { map.put(kvp.key, firstNonNull(kvp.num, kvp.nums, kvp.value, kvp.values, kvp.bool, kvp.bools, unmarshal(kvp.obj), unmarshal(kvp.objs), kvp.any, kvp.anys)); } return map; } // utility method to marshal a nested list of JSON objects protected List<JSON> marshal(List<Map<String, Object>> maps) throws Exception { if (maps == null) return null; List<JSON> result = new ArrayList<JSON>(maps.size()); for (Map<String, Object> e : maps) result.add(marshal(e)); return result; } @Override public JSON marshal(Map<String, Object> map) throws Exception { if (map == null) return null; List<KVP> xml = new ArrayList<KVP>(map.size()); for(Map.Entry<String, Object> mapEntry : map.entrySet()) { KVP entry = new KVP(); entry.key = mapEntry.getKey(); Object v = mapEntry.getValue(); if (v != null) { if (v instanceof List) { List l = (List)v; if (l.size() > 0) { Object w = l.get(0); if (w instanceof Number) entry.nums = l; else if (w instanceof String) entry.values = l; else if (w instanceof Boolean) entry.bools = l; else if (w instanceof Map) entry.objs = marshal((List<Map<String, Object>>)l); else entry.any = v; // fallback } // no action if empty list - cannot determine type, leave null } else { if (v instanceof Number) entry.num = ((Number)v).doubleValue(); else if (v instanceof String) entry.value = (String)v; else if (v instanceof Boolean) entry.bool = (Boolean)v; else if (v instanceof Map) entry.obj = marshal((Map<String, Object>)v); else entry.any = v; // fallback } } xml.add(entry); } JSON result = new JSON(); result.kvp = xml; return result; } }