Jettison is uncapable of deserializing sequences containing something like
"@name":"foo".
So if you can change @XmlAttribute to @XmlElement then it would help.
Now, the other Jettison issue in this example in that it is only capable of
dealing with this sequence only if 'd.' is appended to the root 'definition'
element but not to 'structure'. So if you can update the annotations such
that only the root 'DataDefinition' class has the namespace or no namespace
at all then it would help too.
So you should end up with a sequence like this one :
{"definition": {"repeating":"false","index":"0","name":"Credit Line Increase
Data",
"structure":[{"repeating":"false","index":"2","name":"CreditLineIncConversation",
"symbolic":[
{"index":"0","name":"ReasonForIncrease"},
{"index":"4","name":"TermConds"}
]
}]
}
}
(note that the structure is an array [] now).
There're a lot of preconditions there. in 2.2.4-SNAPSHOT it is possible to
tell a JSONProvider to drop namespaces. More customization will be coming in
later on to deal with the attributes issue and to ensure sequences can be
deserialized into JAXB beans with XmlRootElement containing namespaces.
cheers, Sergey
Sergey Beryozkin wrote:
>
> Actually, I have reproduced it. It reads ok for JAXB but not for JSON. My
> initial thinking is that it is a Jettison (reader) bug, but I'll need to
> play more with this example before I can tell for sure.
> In meantime, you might want to try a Jackson JAXRS provider instead,
> Benson has added the test :
>
> http://svn.apache.org/repos/asf/cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_jackson_provider/WEB-INF/beans.xml
> Or may be wrapping this one : http://code.google.com/p/json-framework/
>
> Perhaps trying to simplify the class hierarchy or JAXB annotations might
> also make the difference.
>
> cheers, Sergey
>
>
> Sergey Beryozkin wrote:
>>
>> Hi
>>
>> I'm having problems with reproducing this issue. I thought I'd do a quick
>> test this evening but I proved to be wrong :-)
>> First I had to modify a bit the classes for a basic test to even start
>> working, to bypass JAXB complaints.
>> So here's what I have now.
>> testIt() results in
>>
>> {"ns1.definition": {"@repeating":"false","@index":"0","@name":"Credit
>> Line Increase Data",
>>
>> "ns1.structure":{"@repeating":"false","@index":"2","@name":"CreditLineIncConversation",
>> "ns1.symbolic":[
>> {"@index":"0","@name":"ReasonForIncrease"},
>> {"@index":"4","@name":"TermConds"}
>> ]
>> }
>> }
>> }
>>
>> which is a simpler but a similar structure instance.
>>
>> @Test
>> public void testIt() throws Exception {
>> JSONProvider p = new JSONProvider();
>> //p.setSerializeAsArray(true);
>> //p.setArrayKeys(Collections.singletonList("structure"));
>>
>> DataDefinition dd = new DataDefinition();
>> dd.setName("Credit Line Increase Data");
>> List<Field> fields = new ArrayList<Field>();
>> Structure s = new Structure();
>> s.setIndex(2);
>> s.setName("CreditLineIncConversation");
>> List<Field> fields2 = new ArrayList<Field>();
>> SymbolicField sf1 = new SymbolicField();
>> sf1.setIndex(0);
>> fields2.add(sf1);
>> sf1.setName("ReasonForIncrease");
>> SymbolicField sf2 = new SymbolicField();
>> sf2.setIndex(4);
>> sf2.setName("TermConds");
>> fields2.add(sf2);
>> s.setFields(fields2);
>> fields.add(s);
>>
>> dd.setFields(fields);
>>
>> ByteArrayOutputStream os = new ByteArrayOutputStream();
>>
>> p.writeTo(dd, (Class)DataDefinition.class, DataDefinition.class,
>> DataDefinition.class.getAnnotations(),
>> MediaType.APPLICATION_JSON_TYPE, new
>> MetadataMap<String, Object>(), os);
>>
>> String str = os.toString();
>> System.out.println(str);
>> }
>>
>>
>> readIt() tries to read this data :
>>
>> @Test
>> public void readIt() throws Exception {
>> String s =
>> "{\"ns1.definition\":{\"@repeating\":\"false\",\"@index\":\"0\",\"@name\":"
>> + "\"Credit Line Increase
>> Data\",\"ns1.structure\":{\"@repeating\":\"false\",\"@index\":\"2\","
>> +
>> "\"@name\":\"CreditLineIncConversation\",\"ns1.symbolic\":[{\"@index\":\"0\",\"@name\":"
>> +
>> "\"ReasonForIncrease\"},{\"@index\":\"4\",\"@name\":\"TermConds\"}]}}}";
>>
>> JSONProvider p = new JSONProvider();
>> Map<String, String> namespaceMap = new HashMap<String, String>();
>> namespaceMap.put("http://bla", "ns1");
>> p.setNamespaceMap(namespaceMap);
>> byte[] bytes = s.getBytes();
>> Object object = p.readFrom((Class)DataDefinition.class,
>> DataDefinition.class,
>> DataDefinition.class.getAnnotations(),
>> null, null, new
>> ByteArrayInputStream(bytes));
>> DataDefinition dd = (DataDefinition)object;
>> Field struct =
>> dd.getFieldsAsMap().get("CreditLineIncConversation");
>> }
>>
>> but gets a ClassCastException at
>> DataDefinition dd = (DataDefinition)object;
>>
>> because it is a Structure object.
>>
>> and here're the slightly updated classes :
>>
>>
>> @XmlRootElement(name = "definition", namespace = "http://bla")
>> public static class DataDefinition extends Structure {
>>
>> }
>>
>> @XmlRootElement(name = "definition", namespace = "http://bla")
>> @XmlSeeAlso({DataDefinition.class, SymbolicField.class})
>>
>> public static class Structure extends Field {
>>
>> @XmlAttribute(required = false)
>> boolean repeating = false;
>>
>> public boolean isRepeating() {
>> return repeating;
>> }
>>
>> @XmlElements( { @XmlElement(name = "structure",
>> namespace="http://bla", type = Structure.class),
>> @XmlElement(name = "numeric", namespace="http://bla",
>> type = NumericField.class),
>> @XmlElement(name = "symbolic",
>> namespace="http://bla", type = SymbolicField.class),
>> @XmlElement(name = "date", namespace="http://bla",
>> type = DateField.class),
>> @XmlElement(name = "boolean", namespace="http://bla",
>> type = BooleanField.class) })
>> private List<Field> fields;
>>
>> // public List<Field> getFields() {
>> // return fields;
>> // }
>>
>> public void setFields(List<Field> fields) {
>> this.fields = fields;
>> }
>>
>> public Map<String, Field> getFieldsAsMap() {
>> Map<String, Field> fieldMap = new HashMap<String,
>> Field>();
>> for (Field field : fields) {
>> fieldMap.put(field.name, field);
>> }
>> return fieldMap;
>> }
>> }
>> @XmlSeeAlso({DataDefinition.class, Structure.class})
>> public static abstract class Field implements Serializable {
>>
>> @XmlAttribute
>> String name;
>>
>> // public String getName() {
>> // return name;
>> // }
>>
>> public void setName(String name) {
>> this.name = name;
>> }
>>
>> @XmlAttribute(required = false)
>> long index;
>>
>> // public long getIndex() {
>> // return index;
>> // }
>> //
>> public void setIndex(long index) {
>> this.index = index;
>> }
>> }
>>
>> @XmlRootElement(name = "symbolic", namespace = "http://bla")
>> public static class SymbolicField extends Field {
>>
>> }
>>
>> public static class NumericField extends Field {
>>
>> }
>>
>> public static class DateField extends Field {
>>
>> }
>>
>> public static class BooleanField extends Field {
>>
>> }
>>
>>
>> Please send me more info which can help me in reproducing it...
>>
>> Cheers, Sergey
>>
>>
>> mraible wrote:
>>>
>>> I'm facing an issue with CXF and JSON marshalling. My GET request for an
>>> object returns the following JSON.
>>>
>>> {
>>> "d.definition":{
>>> "@filename":"credit-line-increase-data",
>>> "@repeating":"false",
>>> "@index":"0",
>>> "@name":"Credit Line Increase Data",
>>> "d.structure":{
>>> "@repeating":"false",
>>> "@index":"0",
>>> "@name":"CreditLineIncConversation",
>>> "d.symbolic":[
>>> {
>>> "@index":"0",
>>> "@name":"ReasonForIncrease"
>>> },
>>> {
>>> "@index":"4",
>>> "@name":"TermsConds"
>>> }
>>> ],
>>> "d.numeric":[
>>> {
>>> "@index":"1",
>>> "@name":"AmountAppliedFor"
>>> },
>>> {
>>> "@index":"2",
>>> "@name":"AmountOffered"
>>> }
>>> ],
>>> "d.boolean":[
>>> {
>>> "@index":"3",
>>> "@name":"CustApprovesCreditCheck"
>>> },
>>> {
>>> "@index":"5",
>>> "@name":"CustAgreesToTermsConds"
>>> }
>>> ],
>>> "d.structure":{
>>> "@repeating":"false",
>>> "@index":"6",
>>> "@name":"CreditCheck",
>>> "d.symbolic":{
>>> "@index":"0",
>>> "@name":"DateOfCreditCheck"
>>> },
>>> "d.structure":{
>>> "@repeating":"true",
>>> "@index":"1",
>>> "@name":"CreditLines",
>>> "d.symbolic":{
>>> "@index":"0",
>>> "@name":"LineType"
>>> },
>>> "d.numeric":[
>>> {
>>> "@index":"1",
>>> "@name":"Amount"
>>> },
>>> {
>>> "@index":"2",
>>> "@name":"DaysPastDue"
>>> }
>>> ]
>>> }
>>> }
>>> }
>>> }
>>> }
>>>
>>> The POST request sends something very similar back (ordering of elements
>>> shouldn't matter hopefully).
>>>
>>> {
>>> "d.definition":{
>>> "@repeating":"false",
>>> "@filename":"credit-line-increase-data",
>>> "@index":"0",
>>> "@name":"Credit Line Increase Data",
>>> "d.structure":{
>>> "@repeating":"false",
>>> "@index":"0",
>>> "@name":"CreditLineIncConversation",
>>> "d.symbolic":[
>>> {
>>> "@index":"0",
>>> "@name":"ReasonForIncrease"
>>> },
>>> {
>>> "@index":"4",
>>> "@name":"TermsConds"
>>> }
>>> ],
>>> "d.numeric":[
>>> {
>>> "@index":"1",
>>> "@name":"AmountAppliedFor"
>>> },
>>> {
>>> "@index":"2",
>>> "@name":"AmountOffered"
>>> }
>>> ],
>>> "d.boolean":[
>>> {
>>> "@index":"3",
>>> "@name":"CustApprovesCreditCheck",
>>> "type":"BOOLEAN"
>>> },
>>> {
>>> "@index":"5",
>>> "@name":"CustAgreesToTermsConds",
>>> "type":"BOOLEAN"
>>> }
>>> ],
>>> "d.structure":{
>>> "@repeating":"false",
>>> "@index":"6",
>>> "@name":"CreditCheck",
>>> "d.symbolic":{
>>> "@index":"0",
>>> "@name":"DateOfCreditCheck"
>>> },
>>> "d.structure":{
>>> "@repeating":"true",
>>> "@index":"1",
>>> "@name":"CreditLines",
>>> "d.symbolic":{
>>> "@index":"0",
>>> "@name":"LineType"
>>> },
>>> "d.numeric":[
>>> {
>>> "@index":"1",
>>> "@name":"Amount"
>>> },
>>> {
>>> "@index":"2",
>>> "@name":"DaysPastDue"
>>> }
>>> ]
>>> }
>>> }
>>> },
>>> "d.structure":{
>>> "d.symbolic":[
>>> {
>>> "@index":"0",
>>> "@name":"ReasonForIncrease"
>>> },
>>> {
>>> "@index":"4",
>>> "@name":"TermsConds"
>>> }
>>> ],
>>> "@repeating":"false",
>>> "@index":"0",
>>> "@name":"CreditLineIncConversation",
>>> "d.boolean":[
>>> {
>>> "@index":"3",
>>> "@name":"CustApprovesCreditCheck",
>>> "type":"BOOLEAN"
>>> },
>>> {
>>> "@index":"5",
>>> "@name":"CustAgreesToTermsConds",
>>> "type":"BOOLEAN"
>>> }
>>> ],
>>> "d.numeric":[
>>> {
>>> "@index":"1",
>>> "@name":"AmountAppliedFor"
>>> },
>>> {
>>> "@index":"2",
>>> "@name":"AmountOffered"
>>> }
>>> ],
>>> "d.structure":{
>>> "@repeating":"false",
>>> "@index":"6",
>>> "@name":"CreditCheck",
>>> "d.symbolic":{
>>> "@index":"0",
>>> "@name":"DateOfCreditCheck"
>>> },
>>> "d.structure":{
>>> "@repeating":"true",
>>> "@index":"1",
>>> "@name":"CreditLines",
>>> "d.symbolic":{
>>> "@index":"0",
>>> "@name":"LineType"
>>> },
>>> "d.numeric":[
>>> {
>>> "@index":"1",
>>> "@name":"Amount"
>>> },
>>> {
>>> "@index":"2",
>>> "@name":"DaysPastDue"
>>> }
>>> ]
>>> }
>>> }
>>> }
>>> }
>>> }
>>>
>>> The bug that I'm currently seeing is that the "symbolic", "boolean" and
>>> "numeric" arrays in the "CreditLineIncConversation" aren't getting
>>> converted from JSON to Java properly. In fact, they're completely
>>> dropped. Here's the resulting JSON after the save has been made:
>>>
>>> {
>>> "d.definition":{
>>> "@filename":"credit-line-increase-data",
>>> "@repeating":"false",
>>> "@index":"0",
>>> "@name":"Credit Line Increase Data",
>>> "d.structure":{
>>> "@repeating":"false",
>>> "@index":"0",
>>> "@name":"CreditLineIncConversation",
>>> "d.structure":{
>>> "@repeating":"false",
>>> "@index":"6",
>>> "@name":"CreditCheck",
>>> "d.symbolic":{
>>> "@index":"0",
>>> "@name":"DateOfCreditCheck"
>>> },
>>> "d.structure":{
>>> "@repeating":"true",
>>> "@index":"1",
>>> "@name":"CreditLines",
>>> "d.symbolic":{
>>> "@index":"0",
>>> "@name":"LineType"
>>> }
>>> }
>>> }
>>> }
>>> }
>>> }
>>>
>>> I tried looking at CXF's JAX-RS Documentation (specifically the json
>>> array serialization issues section) and making the following change in
>>> my configuration.
>>>
>>> @@ -45,8 +45,17 @@
>>> <bean id="jsonProvider"
>>> class="org.apache.cxf.jaxrs.provider.JSONProvider">
>>> <property name="namespaceMap" ref="jsonNamespaceMap"/>
>>> <property name="serializeAsArray" value="true"/>
>>> + <property name="arrayKeys" ref="jsonKeys"/>
>>> </bean>
>>>
>>> + <util:list id="jsonKeys">
>>> + <value>structure</value>
>>> + <value>numeric</value>
>>> + <value>symbolic</value>
>>> + <value>date</value>
>>> + <value>boolean</value>
>>> + </util:list>
>>> +
>>>
>>> Unfortunately, this didn't work.
>>>
>>> The class that I'm trying to populate is defined as:
>>>
>>> @XmlRootElement(name = "definition")
>>> public class DataDefinition extends Structure {
>>>
>>> }
>>>
>>> It's parent (Structure), looks as follows:
>>>
>>> public class Structure extends Field {
>>>
>>> @XmlAttribute(required = false)
>>> boolean repeating = false;
>>>
>>> public boolean isRepeating() {
>>> return repeating;
>>> }
>>>
>>> @XmlElements( { @XmlElement(name = "structure", type =
>>> Structure.class),
>>> @XmlElement(name = "numeric", type = NumericField.class),
>>> @XmlElement(name = "symbolic", type = SymbolicField.class),
>>> @XmlElement(name = "date", type = DateField.class),
>>> @XmlElement(name = "boolean", type = BooleanField.class) })
>>> private List<Field> fields;
>>>
>>> public List<Field> getFields() {
>>> return fields;
>>> }
>>>
>>> public void setFields(List<Field> fields) {
>>> this.fields = fields;
>>> }
>>>
>>> public Map<String, Field> getFieldsAsMap() {
>>> Map<String, Field> fieldMap = new HashMap<String, Field>();
>>> for (Field field : getFields()) {
>>> fieldMap.put(field.getName(), field);
>>> }
>>> return fieldMap;
>>> }
>>> }
>>>
>>> I'd appreciate any pointers on what I need to do to make this work.
>>>
>>> Thanks!
>>>
>>> Matt
>>>
>>
>>
>
>
--
View this message in context:
http://www.nabble.com/Issues-marshalling-a-JSON-String-to-Java-Objects-%28works-fine-from-Java-to-JSON%29-tp25531242p25649683.html
Sent from the cxf-user mailing list archive at Nabble.com.