접기
1차적으로 그냥 HashMap 형식으로 Marshaller 를 만들어서 처리를 하였으나...
1
Marshaller marshaller = JAXBContext.newInstance(HashMap.
class
).createMarshaller();
2
marshaller.setProperty(Marshaller.JAXB_ENCODING,
"UTF-8"
);
3
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
true
);
결과는
javax.xml.bind.MarshalException
- with linked exception:
[com.sun.istack.internal.SAXException2: unable to marshal type "java.util.HashMap" as an element because it is missing an @XmlRootElement annotation]
안되는 것이지요...
그래서 클래스로 감싸서 처리해보았습니다.
ContentData.java
01
import
java.io.StringReader;
02
import
java.io.StringWriter;
05
import
javax.xml.bind.JAXBContext;
06
import
javax.xml.bind.Marshaller;
07
import
javax.xml.bind.Unmarshaller;
08
import
javax.xml.bind.annotation.XmlAccessType;
09
import
javax.xml.bind.annotation.XmlAccessorType;
10
import
javax.xml.bind.annotation.XmlRootElement;
12
@XmlAccessorType
(XmlAccessType.FIELD)
13
@XmlRootElement
(name =
"content"
)
14
public
class
ContentData {
16
private
Map contentMap;
18
public
Map getContentMap() {
22
public
void
setContentMap(Map contentMap) {
23
this
.contentMap = contentMap;
26
private
static
Marshaller marshaller;
28
private
static
Unmarshaller unmarshaller;
30
public
static
String marshalling(ContentData contentData) {
31
StringWriter writer =
new
StringWriter();
34
if
(marshaller ==
null
) {
35
marshaller = JAXBContext.newInstance(ContentData.
class
).createMarshaller();
36
marshaller.setProperty(Marshaller.JAXB_ENCODING,
"UTF-8"
);
37
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
true
);
40
marshaller.marshal(contentData, writer);
41
}
catch
(Exception e) {
45
return
writer.toString();
48
public
static
ContentData unmarshalling(String data) {
49
ContentData contentData =
null
;
50
StringReader reader =
new
StringReader(data);
52
if
(unmarshaller ==
null
) {
53
unmarshaller = JAXBContext.newInstance(ContentData.
class
).createUnmarshaller();
56
contentData = (ContentData) unmarshaller.unmarshal(reader);
57
}
catch
(Exception e) {
테스트는 아래와 같이 한 후 확인해보면...
1
ContentData contentData =
new
ContentData();
2
Map map =
new
HashMap();
4
map.put(
"abc1"
,
"abcd"
);
5
contentData.setContentMap(map);
7
String data = ContentData.marshalling(contentData);
8
System.out.println(data);
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<content>
<contentMap>
<entry>
<key xsi:type="xs:string" xmlns:xs=" http://www.w3.org/2001/XMLSchema " xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance">abc</key >
<value xsi:type="xs:string" xmlns:xs=" http://www.w3.org/2001/XMLSchema " xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance">abcd</value >
</entry>
<entry>
<key xsi:type="xs:string" xmlns:xs=" http://www.w3.org/2001/XMLSchema " xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance">abc1</key >
<value xsi:type="xs:string" xmlns:xs=" http://www.w3.org/2001/XMLSchema " xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance">abcd</value >
</entry>
</contentMap>
</content>
필요 없는 데이터가 길어져버렸습니다.
이러면 안되기에 JavaDoc 을 더 훑어본 후
@XmlJavaTypeAdapter 라는 것을 찾아내었습니다.
ContentData 클래스의 contentData 객체의 어노테이션을 추가합니다.
1
public
class
ContentData {
3
@XmlJavaTypeAdapter
(value=HashMapAdapter.
class
)
4
private
Map contentMap;
HashMapAdapter.java
01
import
java.util.ArrayList;
02
import
java.util.HashMap;
03
import
java.util.Iterator;
07
import
javax.xml.bind.annotation.adapters.XmlAdapter;
09
class
HashMapAdapter
extends
XmlAdapter<KeyValuePair[], Map<String, String>> {
11
public
HashMapAdapter() {
16
public
KeyValuePair[] marshal(Map<String, String> v)
throws
Exception {
17
List<KeyValuePair> list =
new
ArrayList<KeyValuePair>();
19
for
(Iterator<String> it = v.keySet().iterator(); it.hasNext(); ) {
20
String key = it.next();
21
String value = v.get(key);
22
list.add(
new
KeyValuePair(key, value));
25
return
list.toArray(
new
KeyValuePair[
0
]);
29
public
Map<String, String> unmarshal(KeyValuePair[] v)
throws
Exception {
30
Map<String, String> contentMap =
new
HashMap<String, String>();
32
for
(KeyValuePair pair : v) {
33
contentMap.put(pair.getKey(), pair.getValue());
KeyValuePair.java
01
import
javax.xml.bind.annotation.XmlAccessType;
02
import
javax.xml.bind.annotation.XmlAccessorType;
03
import
javax.xml.bind.annotation.XmlAttribute;
05
@XmlAccessorType
(XmlAccessType.FIELD)
06
public
class
KeyValuePair {
14
public
KeyValuePair() {
18
public
KeyValuePair(String key, String value) {
24
public
String getKey() {
28
public
void
setKey(String key) {
32
public
String getValue() {
36
public
void
setValue(String value) {
테스트를 해보았습니다.
01
ContentData contentData =
new
ContentData();
02
Map map =
new
HashMap();
03
map.put(
"abc"
,
"abcd"
);
04
map.put(
"abc1"
,
"abcd"
);
05
contentData.setContentMap(map);
07
String data = ContentData.marshalling(contentData);
08
System.out.println(data);
10
ContentData contentData2 = ContentData.unmarshalling(data);
11
System.out.println(contentData2.getContentMap());
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<content>
<contentMap>
<item value="abcd" key="abc"/>
<item value="abcd" key="abc1"/>
</contentMap>
</content>
{abc=abcd, abc1=abcd}
Marshalling 도 잘되고
Unmarshalling 도 잘됩니다. ㅋㅋㅋ
접기
원래 JAXB 는 JAX-WS 때문에 나온 거 같은데 요긴하게 잘 써먹고 있습니다.