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-tp25531242p25636080.html Sent from the cxf-user mailing list archive at Nabble.com.
