JAXB java.util.Map binding
Asked Answered
B

1

14

I have a Json response which looks like the following:

{
    "data": [
        {
            "param1": "value1",
            "param2": "value2",
                    .
                    .
                    .
            "paramN": "valueN"
        }
    ]
}

I don't know the name and the number of the parameters. So, I need and want to bind all these parameters to a java.util.Map field consisting of <"paramX", "valueX"> tuples. To do this, I tried the following code but "parametersMap" field returns null.

@XmlRootElement(name="data")
@XmlAccessorType(XmlAccessType.FIELD)
public class Parameters {
    @XmlElement
    private Map<String,String> parametersMap;

    // Getter and setter for parametersMap
}

How can I achieve such a binding with JAXB annotations?

Thanks in advance.

Bagworm answered 28/2, 2012 at 7:52 Comment(7)
From a different post I just learned that jersey (re)uses JAXB annotations. #1262093Fascicle
Yes, JAXB is for XML binding but it can be also used to bind JSON inputs to Java objects together with Jersey.Bagworm
EclipseLink JAXB (MOXy) also offers JSON binding leveraging JAXB annotations: blog.bdoughan.com/2011/08/…Tacho
which version of Jersey are you using?Bole
I'm using jersey-client and jersey-json of version 1.12Bagworm
I think this link can help you: #6253077Algol
Jackson json library can also use JAXB annotations.Renell
R
8

Basically you need an xml adapter. You can fiddle with the names on the KeyValue class to get the specific output you desire.

Parameter.java

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.Map;

@XmlRootElement(name = "data")
@XmlAccessorType(XmlAccessType.FIELD)
public class Parameters {

    @XmlJavaTypeAdapter(value = Adapter.class)
    private Map<String, String> parametersMap;

    // Getter and setter for parametersMap
}

Adapter.java

import javax.xml.bind.annotation.adapters.XmlAdapter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Adapter extends XmlAdapter<List<KeyValue>, Map<String, String>> {

    @Override
    public Map<String, String> unmarshal(List<KeyValue> v) throws Exception {
        Map<String, String> map = new HashMap<>(v.size());
        for (KeyValue keyValue : v) {
            map.put(keyValue.key, keyValue.value);
        }
        return map;
    }

    @Override
    public List<KeyValue> marshal(Map<String, String> v) throws Exception {
        Set<String> keys = v.keySet();
        List<KeyValue> results = new ArrayList<>(v.size());
        for (String key : keys) {
            results.add(new KeyValue(key, v.get(key)));
        }
        return results;
    }
}

KeyValue.java Put better JAXB tags here, obviously.

import javax.xml.bind.annotation.XmlType;

@XmlType
public class KeyValue {
    public KeyValue() {
    }

    public KeyValue(String key, String value) {
        this.key = key;
        this.value = value;
    }

    //obviously needs setters/getters
    String key;
    String value;
}
Renell answered 19/4, 2012 at 6:4 Comment(2)
I get com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions for Parameters.java at the line where the Map is declared.Piano
The answer tomasmalmsten.com/2012/05/… wraps List<KeyValue> in another helper class. This prevents that IllegalAnnotationsException.Piano

© 2022 - 2024 — McMap. All rights reserved.