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