Last active
June 5, 2020 18:40
-
-
Save ricardojlrufino/8b0094bcf9c74b630274af50fe7cd831 to your computer and use it in GitHub Desktop.
JAXB - Serialize Map<String, Object> (problem)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.ricardojlrufino.rhmitool.controller.configuration.example; | |
public class Address { | |
private String street; | |
private String city; | |
public String getStreet() { | |
return street; | |
} | |
public void setStreet(String street) { | |
this.street = street; | |
} | |
public String getCity() { | |
return city; | |
} | |
public void setCity(String city) { | |
this.city = city; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.ricardojlrufino.rhmitool.controller.configuration.example; | |
public interface CustomSerializer<T> { | |
String serialize(T value); | |
T deserialize(String value); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.ricardojlrufino.rhmitool.controller.configuration.example; | |
import java.awt.Point; | |
import java.util.Arrays; | |
import javax.xml.bind.JAXBContext; | |
import javax.xml.bind.Marshaller; | |
public class Demo { | |
public static void main(String[] args) throws Exception { | |
JAXBContext jc = JAXBContext.newInstance( | |
Method.class, | |
KeyValue.class, | |
Address.class, | |
Point.class | |
); | |
KeyValueAdapter adapter = new KeyValueAdapter(jc); | |
adapter.addSerializer(Point.class, new PointSerializer()); | |
Method action = new Method(); | |
action.setParameters(Arrays.asList(new KeyValue("name1", 100), | |
new KeyValue("name2", new Point(1, 2)), | |
new KeyValue("addr", new Address()) | |
)); | |
Marshaller marshaller = jc.createMarshaller(); | |
marshaller.setAdapter(adapter); | |
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); | |
marshaller.marshal(action, System.out); | |
// Unmarshaller unmarshaller = jc.createUnmarshaller(); | |
// unmarshaller.setAdapter(adapter); | |
// File xml = new File("/media/ricardo/Dados/Workspace/Arduino/RHMI-Tool/HMIController/src/main/java/com/ricardojlrufino/rhmitool/controller/configuration/example/test.xml"); | |
// Method action = (Method) unmarshaller.unmarshal(xml); | |
// System.out.println(action.getParameters()); | |
// JAXBContext conetxt = JAXBContext.newInstance(java.awt.Point.class); | |
// Marshaller marshaller = conetxt.createMarshaller(); | |
//// marshaller.marshal( new JAXBElement( | |
//// new QName("","rootTag"),Point.class,new Point(1, 2)), System.out); | |
// | |
// QName rootElement = new QName("attrName"); | |
// Object value = new Point(1, 2); | |
// Class<?> type = value.getClass(); | |
// JAXBElement jaxbElement = new JAXBElement(rootElement, type, value); | |
// marshaller.marshal(jaxbElement, System.out); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.ricardojlrufino.rhmitool.controller.configuration.example; | |
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; | |
@XmlJavaTypeAdapter(KeyValueAdapter.class) | |
public class KeyValue { | |
private String name; | |
private Object value; | |
public KeyValue() { | |
super(); | |
} | |
public KeyValue(String name, Object value) { | |
super(); | |
this.name = name; | |
this.value = value; | |
} | |
public String getName() { | |
return name; | |
} | |
public void setName(String name) { | |
this.name = name; | |
} | |
public Object getValue() { | |
return value; | |
} | |
public void setValue(Object value) { | |
this.value = value; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.ricardojlrufino.rhmitool.controller.configuration.jaxb; | |
import java.util.HashMap; | |
import javax.xml.bind.JAXBContext; | |
import javax.xml.bind.JAXBElement; | |
import javax.xml.bind.Marshaller; | |
import javax.xml.bind.Unmarshaller; | |
import javax.xml.bind.annotation.adapters.XmlAdapter; | |
import javax.xml.namespace.QName; | |
import javax.xml.parsers.DocumentBuilder; | |
import javax.xml.parsers.DocumentBuilderFactory; | |
import javax.xml.transform.dom.DOMSource; | |
import org.w3c.dom.Document; | |
import org.w3c.dom.Element; | |
public class KeyValueAdapter extends XmlAdapter<Element, KeyValue> { | |
private ClassLoader classLoader; | |
private DocumentBuilder documentBuilder; | |
private JAXBContext jaxbContext; | |
private HashMap<Class, CustomSerializer> serializers = new HashMap<>(); | |
public KeyValueAdapter() { | |
classLoader = Thread.currentThread().getContextClassLoader(); | |
} | |
public KeyValueAdapter(JAXBContext jaxbContext) { | |
this(); | |
this.jaxbContext = jaxbContext; | |
} | |
public <T> void addSerializer(Class<T> key, CustomSerializer<T> value) { | |
serializers.put(key, value); | |
} | |
private DocumentBuilder getDocumentBuilder() throws Exception { | |
// Lazy load the DocumentBuilder as it is not used for unmarshalling. | |
if (null == documentBuilder) { | |
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); | |
documentBuilder = dbf.newDocumentBuilder(); | |
} | |
return documentBuilder; | |
} | |
private JAXBContext getJAXBContext(Class<?> type) throws Exception { | |
if (null == jaxbContext) { | |
// A JAXBContext was not set, so create a new one based on the type. | |
return JAXBContext.newInstance(type); | |
} | |
return jaxbContext; | |
} | |
@Override | |
public Element marshal(KeyValue parameter) throws Exception { | |
if (null == parameter) { | |
return null; | |
} | |
Object value = parameter.getValue(); | |
Class type = value.getClass(); | |
// Custom serializers.. | |
CustomSerializer customSerializer = serializers.get(type); | |
if(customSerializer != null) { | |
value = customSerializer.serialize(value); | |
} | |
// 1. Build the JAXBElement to wrap the instance of Parameter. | |
QName rootElement = new QName(parameter.getName()); | |
JAXBElement jaxbElement = new JAXBElement(rootElement, type, value); | |
// 2. Marshal the JAXBElement to a DOM element. | |
Document document = getDocumentBuilder().newDocument(); | |
Marshaller marshaller = getJAXBContext(type).createMarshaller(); | |
marshaller.marshal(jaxbElement, document); | |
Element element = document.getDocumentElement(); | |
// 3. Set the type attribute based on the value's type. | |
element.setAttribute("type", type.getName()); | |
return element; | |
} | |
@Override | |
public KeyValue unmarshal(Element element) throws Exception { | |
if (null == element) { | |
return null; | |
} | |
// 1. Determine the values type from the type attribute. | |
Class<?> type = classLoader.loadClass(element.getAttribute("type")); | |
// Custom serializers.. | |
CustomSerializer customSerializer = serializers.get(type); | |
if(customSerializer != null) { | |
Object value = customSerializer.deserialize(element.getTextContent()); | |
KeyValue parameter = new KeyValue(); | |
parameter.setName(element.getLocalName()); | |
parameter.setValue(value); | |
return parameter; | |
}else { | |
// 2. Unmarshal the element based on the value's type. | |
DOMSource source = new DOMSource(element); | |
Unmarshaller unmarshaller = getJAXBContext(type).createUnmarshaller(); | |
JAXBElement jaxbElement = unmarshaller.unmarshal(source, type); | |
// 3. Build the instance of Parameter | |
KeyValue parameter = new KeyValue(); | |
parameter.setName(element.getLocalName()); | |
parameter.setValue(jaxbElement.getValue()); | |
return parameter; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.ricardojlrufino.rhmitool.controller.configuration.example; | |
import java.util.List; | |
import javax.xml.bind.annotation.XmlAnyElement; | |
import javax.xml.bind.annotation.XmlAttribute; | |
import javax.xml.bind.annotation.XmlRootElement; | |
@XmlRootElement | |
public class Method { | |
private String name; | |
private List<KeyValue> parameters; | |
@XmlAttribute | |
public String getName() { | |
return name; | |
} | |
public void setName(String name) { | |
this.name = name; | |
} | |
@XmlAnyElement | |
public List<KeyValue> getParameters() { | |
return parameters; | |
} | |
public void setParameters(List<KeyValue> parameters) { | |
this.parameters = parameters; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.ricardojlrufino.rhmitool.controller.configuration.example; | |
import java.awt.Point; | |
public class PointSerializer implements CustomSerializer<Point> { | |
@Override | |
public String serialize(Point value) { | |
return value.getX()+","+value.getY(); | |
} | |
@Override | |
public Point deserialize(String value) { | |
return new Point(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment