You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by mraible <ma...@raibledesigns.com> on 2009/10/06 22:14:25 UTC
Re: Issues marshalling a JSON String to Java Objects (works fine
from Java to JSON)
Sorry for not replying sooner - I thought I was subscribed to this thread in
Nabble, but apparently wasn't.
>From your explanation, it sounds like I should try using CXF 2.2.4-SNAPSHOT
and changing some annotations to @XmlElement. Is that correct?
Is this bug something that would affect other JSON providers like Jackson
too? I've heard it's 10x faster[1] and since I current have a patched
version of Jettison[2], it might make sense to switch.
Lastly, is there a JIRA issue for this that I can track or reference?
Thanks,
Matt
[1] http://markmail.org/message/btngjg67rithzcv5
[2] http://jira.codehaus.org/browse/JETTISON-57
Sergey Beryozkin wrote:
>
> 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-tp25531242p25775811.html
Sent from the cxf-user mailing list archive at Nabble.com.
RE: Issues marshalling a JSON String to Java Objects (works fine
from Java to JSON)
Posted by Sergey Beryozkin <se...@iona.com>.
> I'm working in background on making sure one can do pretty much any sort of
transformation (well, most simple enough transformations :-))
Finally I've committed some initial support for it.
It should be possible to easily :
- drop elements, namespaces, attributes
- change names, namespaces
- append elements
- require attributes be serialized as elements, etc...
on the in/out
I'll be working on updating the docs later on
Sergey
Sergey Beryozkin wrote:
>
> Hi Matt
>
> Thanks for confirming it.
> I'm working in background on making sure one can do pretty much any sort
> of transformation (well, most simple enough transformations :-)) to
> JAXB-based outputs without having to deal with writing
> XMLStreamWriters/Readers but it will take me a bit of time.
> In 2.2.4 you can have namespaces dropped for JSON production only, to
> append them back you'd need to register a custom XMLStreamReader - it
> won't be needed once I'm done with my work.
>
> It all goes pretty well for JAXB/XML but Jettison writer/reader need some
> fixes along the way; I'll work with the local Jettison build (with your
> patch being included)
>
> Cheers, Sergey
>
>
> mraible wrote:
>>
>> I was able to get everything working by changing @XmlAttribute to
>> @XmlElement and setting namespace="" to many elements. I'm not sure if
>> this is a workable solution on my project since we're using JAXB for XML
>> and I think the namespaces need to be there for that.
>>
>> For CXF 2.2.4, will it be possible to drop the namespaces for JSON
>> production/consumption only? Or will it affect XML as well?
>>
>> As far as the patch I submitted to Jettison, that is necessary to get
>> JSON to show up in the proper hierarchy. Without it, some children show
>> up in a parent where they shouldn't.
>>
>> Thanks,
>>
>> Matt
>>
>>
>> Sergey Beryozkin-2 wrote:
>>>
>>> Hi
>>>
>>> Having @XmlAttribute annotations causes Jettison to fail to deserialize
>>> the sequence you posted originally given that it causes it to serialize
>>> "@name":"bar" like properties in the first place. So I was able to write
>>> a test reading the sequence with CXF 2.2.3 as suggested in [1] (but I
>>> also had to ensure only the first root element was namespace-qualified).
>>>
>>> I've been working in background on making sure a user can customize most
>>> of the serialization process for JAXB/JSON (drop namespaces - possible
>>> in 2.4-SNAPSHOT, have a given node serialized with a diff local name,
>>> with/without namespace), additionally for JSON : cause attributes be
>>> serialized as elements, etc but I'll most likely won't finish it in time
>>> for 2.2.4
>>>
>>> By the way, how does the patch for [2] helps in dealing with this issue
>>> ?
>>>
>>>> Is this bug something that would affect other JSON providers like
>>> Jackson
>>> too?
>>>
>>> Probably not - but I'm not exactly sure
>>>
>>>> I've heard it's 10x faster
>>>
>>> Possibly. Jettison does not do streaming which is something Dejan might
>>> get a chance to look into.
>>>
>>> Cheers, Sergey
>>>
>>> [1]
>>> http://www.nabble.com/Issues-marshalling-a-JSON-String-to-Java-Objects-(
>>> works-fine-from-Java-to-JSON)-tt25531242.html#a25775811
>>> [2] http://jira.codehaus.org/browse/JETTISON-57
>>>
>>> -----Original Message-----
>>> From: mraible [mailto:matt@raibledesigns.com]
>>> Sent: 06 October 2009 21:14
>>> To: users@cxf.apache.org
>>> Subject: Re: Issues marshalling a JSON String to Java Objects (works
>>> fine from Java to JSON)
>>>
>>>
>>> Sorry for not replying sooner - I thought I was subscribed to this
>>> thread in
>>> Nabble, but apparently wasn't.
>>>
>>> From your explanation, it sounds like I should try using CXF
>>> 2.2.4-SNAPSHOT
>>> and changing some annotations to @XmlElement. Is that correct?
>>>
>>> Is this bug something that would affect other JSON providers like
>>> Jackson
>>> too? I've heard it's 10x faster[1] and since I current have a patched
>>> version of Jettison[2], it might make sense to switch.
>>>
>>> Lastly, is there a JIRA issue for this that I can track or reference?
>>>
>>> Thanks,
>>>
>>> Matt
>>>
>>> [1] http://markmail.org/message/btngjg67rithzcv5
>>> [2] http://jira.codehaus.org/browse/JETTISON-57
>>>
>>>
>>> Sergey Beryozkin wrote:
>>>>
>>>> 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":"CreditLineIncConve
>>> rsation",
>>>> "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/resour
>>> ces/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":"CreditLineIn
>>> cConversation",
>>>>>> "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-tp25531242p25775811.html
>>> Sent from the cxf-user mailing list archive at Nabble.com.
>>>
>>>
>>>
>>
>>
>
>
--
View this message in context: http://old.nabble.com/Issues-marshalling-a-JSON-String-to-Java-Objects-%28works-fine-from-Java-to-JSON%29-tp25531242p26256808.html
Sent from the cxf-user mailing list archive at Nabble.com.
RE: Issues marshalling a JSON String to Java Objects (works fine
from Java to JSON)
Posted by Sergey Beryozkin <se...@iona.com>.
Hi Matt
Thanks for confirming it.
I'm working in background on making sure one can do pretty much any sort of
transformation (well, most simple enough transformations :-)) to JAXB-based
outputs without having to deal with writing XMLStreamWriters/Readers but it
will take me a bit of time.
In 2.2.4 you can have namespaces dropped for JSON production only, to append
them back you'd need to register a custom XMLStreamReader - it won't be
needed once I'm done with my work.
It all goes pretty well for JAXB/XML but Jettison writer/reader need some
fixes along the way; I'll work with the local Jettison build (with your
patch being included)
Cheers, Sergey
mraible wrote:
>
> I was able to get everything working by changing @XmlAttribute to
> @XmlElement and setting namespace="" to many elements. I'm not sure if
> this is a workable solution on my project since we're using JAXB for XML
> and I think the namespaces need to be there for that.
>
> For CXF 2.2.4, will it be possible to drop the namespaces for JSON
> production/consumption only? Or will it affect XML as well?
>
> As far as the patch I submitted to Jettison, that is necessary to get JSON
> to show up in the proper hierarchy. Without it, some children show up in a
> parent where they shouldn't.
>
> Thanks,
>
> Matt
>
>
> Sergey Beryozkin-2 wrote:
>>
>> Hi
>>
>> Having @XmlAttribute annotations causes Jettison to fail to deserialize
>> the sequence you posted originally given that it causes it to serialize
>> "@name":"bar" like properties in the first place. So I was able to write
>> a test reading the sequence with CXF 2.2.3 as suggested in [1] (but I
>> also had to ensure only the first root element was namespace-qualified).
>>
>> I've been working in background on making sure a user can customize most
>> of the serialization process for JAXB/JSON (drop namespaces - possible
>> in 2.4-SNAPSHOT, have a given node serialized with a diff local name,
>> with/without namespace), additionally for JSON : cause attributes be
>> serialized as elements, etc but I'll most likely won't finish it in time
>> for 2.2.4
>>
>> By the way, how does the patch for [2] helps in dealing with this issue
>> ?
>>
>>> Is this bug something that would affect other JSON providers like
>> Jackson
>> too?
>>
>> Probably not - but I'm not exactly sure
>>
>>> I've heard it's 10x faster
>>
>> Possibly. Jettison does not do streaming which is something Dejan might
>> get a chance to look into.
>>
>> Cheers, Sergey
>>
>> [1]
>> http://www.nabble.com/Issues-marshalling-a-JSON-String-to-Java-Objects-(
>> works-fine-from-Java-to-JSON)-tt25531242.html#a25775811
>> [2] http://jira.codehaus.org/browse/JETTISON-57
>>
>> -----Original Message-----
>> From: mraible [mailto:matt@raibledesigns.com]
>> Sent: 06 October 2009 21:14
>> To: users@cxf.apache.org
>> Subject: Re: Issues marshalling a JSON String to Java Objects (works
>> fine from Java to JSON)
>>
>>
>> Sorry for not replying sooner - I thought I was subscribed to this
>> thread in
>> Nabble, but apparently wasn't.
>>
>> From your explanation, it sounds like I should try using CXF
>> 2.2.4-SNAPSHOT
>> and changing some annotations to @XmlElement. Is that correct?
>>
>> Is this bug something that would affect other JSON providers like
>> Jackson
>> too? I've heard it's 10x faster[1] and since I current have a patched
>> version of Jettison[2], it might make sense to switch.
>>
>> Lastly, is there a JIRA issue for this that I can track or reference?
>>
>> Thanks,
>>
>> Matt
>>
>> [1] http://markmail.org/message/btngjg67rithzcv5
>> [2] http://jira.codehaus.org/browse/JETTISON-57
>>
>>
>> Sergey Beryozkin wrote:
>>>
>>> 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":"CreditLineIncConve
>> rsation",
>>> "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/resour
>> ces/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":"CreditLineIn
>> cConversation",
>>>>> "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-tp25531242p25775811.html
>> Sent from the cxf-user mailing list archive at Nabble.com.
>>
>>
>>
>
>
--
View this message in context: http://www.nabble.com/Issues-marshalling-a-JSON-String-to-Java-Objects-%28works-fine-from-Java-to-JSON%29-tp25531242p25827165.html
Sent from the cxf-user mailing list archive at Nabble.com.
RE: Issues marshalling a JSON String to Java Objects (works fine
from Java to JSON)
Posted by mraible <ma...@raibledesigns.com>.
I was able to get everything working by changing @XmlAttribute to @XmlElement
and setting namespace="" to many elements. I'm not sure if this is a
workable solution on my project since we're using JAXB for XML and I think
the namespaces need to be there for that.
For CXF 2.2.4, will it be possible to drop the namespaces for JSON
production/consumption only? Or will it affect XML as well?
As far as the patch I submitted to Jettison, that is necessary to get JSON
to show up in the proper hierarchy. Without it, some children show up in a
parent where they shouldn't.
Thanks,
Matt
Sergey Beryozkin-2 wrote:
>
> Hi
>
> Having @XmlAttribute annotations causes Jettison to fail to deserialize
> the sequence you posted originally given that it causes it to serialize
> "@name":"bar" like properties in the first place. So I was able to write
> a test reading the sequence with CXF 2.2.3 as suggested in [1] (but I
> also had to ensure only the first root element was namespace-qualified).
>
> I've been working in background on making sure a user can customize most
> of the serialization process for JAXB/JSON (drop namespaces - possible
> in 2.4-SNAPSHOT, have a given node serialized with a diff local name,
> with/without namespace), additionally for JSON : cause attributes be
> serialized as elements, etc but I'll most likely won't finish it in time
> for 2.2.4
>
> By the way, how does the patch for [2] helps in dealing with this issue
> ?
>
>> Is this bug something that would affect other JSON providers like
> Jackson
> too?
>
> Probably not - but I'm not exactly sure
>
>> I've heard it's 10x faster
>
> Possibly. Jettison does not do streaming which is something Dejan might
> get a chance to look into.
>
> Cheers, Sergey
>
> [1]
> http://www.nabble.com/Issues-marshalling-a-JSON-String-to-Java-Objects-(
> works-fine-from-Java-to-JSON)-tt25531242.html#a25775811
> [2] http://jira.codehaus.org/browse/JETTISON-57
>
> -----Original Message-----
> From: mraible [mailto:matt@raibledesigns.com]
> Sent: 06 October 2009 21:14
> To: users@cxf.apache.org
> Subject: Re: Issues marshalling a JSON String to Java Objects (works
> fine from Java to JSON)
>
>
> Sorry for not replying sooner - I thought I was subscribed to this
> thread in
> Nabble, but apparently wasn't.
>
> From your explanation, it sounds like I should try using CXF
> 2.2.4-SNAPSHOT
> and changing some annotations to @XmlElement. Is that correct?
>
> Is this bug something that would affect other JSON providers like
> Jackson
> too? I've heard it's 10x faster[1] and since I current have a patched
> version of Jettison[2], it might make sense to switch.
>
> Lastly, is there a JIRA issue for this that I can track or reference?
>
> Thanks,
>
> Matt
>
> [1] http://markmail.org/message/btngjg67rithzcv5
> [2] http://jira.codehaus.org/browse/JETTISON-57
>
>
> Sergey Beryozkin wrote:
>>
>> 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":"CreditLineIncConve
> rsation",
>> "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/resour
> ces/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":"CreditLineIn
> cConversation",
>>>> "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-tp25531242p25775811.html
> Sent from the cxf-user mailing list archive at Nabble.com.
>
>
>
--
View this message in context: http://www.nabble.com/Issues-marshalling-a-JSON-String-to-Java-Objects-%28works-fine-from-Java-to-JSON%29-tp25531242p25825764.html
Sent from the cxf-user mailing list archive at Nabble.com.
RE: Issues marshalling a JSON String to Java Objects (works fine from Java to JSON)
Posted by Sergey Beryozkin <sb...@progress.com>.
Hi
Having @XmlAttribute annotations causes Jettison to fail to deserialize
the sequence you posted originally given that it causes it to serialize
"@name":"bar" like properties in the first place. So I was able to write
a test reading the sequence with CXF 2.2.3 as suggested in [1] (but I
also had to ensure only the first root element was namespace-qualified).
I've been working in background on making sure a user can customize most
of the serialization process for JAXB/JSON (drop namespaces - possible
in 2.4-SNAPSHOT, have a given node serialized with a diff local name,
with/without namespace), additionally for JSON : cause attributes be
serialized as elements, etc but I'll most likely won't finish it in time
for 2.2.4
By the way, how does the patch for [2] helps in dealing with this issue
?
> Is this bug something that would affect other JSON providers like
Jackson
too?
Probably not - but I'm not exactly sure
> I've heard it's 10x faster
Possibly. Jettison does not do streaming which is something Dejan might
get a chance to look into.
Cheers, Sergey
[1]
http://www.nabble.com/Issues-marshalling-a-JSON-String-to-Java-Objects-(
works-fine-from-Java-to-JSON)-tt25531242.html#a25775811
[2] http://jira.codehaus.org/browse/JETTISON-57
-----Original Message-----
From: mraible [mailto:matt@raibledesigns.com]
Sent: 06 October 2009 21:14
To: users@cxf.apache.org
Subject: Re: Issues marshalling a JSON String to Java Objects (works
fine from Java to JSON)
Sorry for not replying sooner - I thought I was subscribed to this
thread in
Nabble, but apparently wasn't.
>From your explanation, it sounds like I should try using CXF
2.2.4-SNAPSHOT
and changing some annotations to @XmlElement. Is that correct?
Is this bug something that would affect other JSON providers like
Jackson
too? I've heard it's 10x faster[1] and since I current have a patched
version of Jettison[2], it might make sense to switch.
Lastly, is there a JIRA issue for this that I can track or reference?
Thanks,
Matt
[1] http://markmail.org/message/btngjg67rithzcv5
[2] http://jira.codehaus.org/browse/JETTISON-57
Sergey Beryozkin wrote:
>
> 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":"CreditLineIncConve
rsation",
> "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/resour
ces/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":"CreditLineIn
cConversation",
>>> "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-tp25531242p25775811.html
Sent from the cxf-user mailing list archive at Nabble.com.