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:[email protected]] 
> Sent: 06 October 2009 21:14
> To: [email protected]
> 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.

Reply via email to