JSON Unmarshalling Issue

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

JSON Unmarshalling Issue

Ni Yue
Hello,

I am using Jersey to serve JSON response and met some issue. In my case, I used JAXB for XML marshalling and used Jersey's build-in function to map XML to JSON. And there're multiple namespaces in my XML schema, for example:

base.xsd:

<?xml version="1.0" encoding="UTF-8"?>
<schema
    xmlns="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:base="http://fruitbase.example.org"
    targetNamespace="http://fruitbase.example.org"
    elementFormDefault="qualified">
   
    <element name="fruits">
        <complexType>
            <sequence>
                <element name="fruit" type="base:Fruit" minOccurs="0"></element>
            </sequence>
        </complexType>
    </element>
   
    <complexType name="Fruit">
        <sequence>
            <element name="name" type="string"/>
            <element name="color" type="string"/>
        </sequence>
    </complexType>
</schema>

fruits.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<schema
    xmlns="http://www.w3.org/2001/XMLSchema"
    xmlns:base="http://fruitbase.example.org"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:fruits="http://fruits.example.org"
    targetNamespace="http://fruits.example.org"
    elementFormDefault="qualified">
    <import namespace="http://fruitbase.example.org" schemaLocation="base.xsd"></import>
    <complexType name="Apple">
        <complexContent>
            <extension base="base:Fruit">
                <sequence>
                    <element name="weight" type="int"></element>
                </sequence>
                <anyAttribute/>
            </extension>
        </complexContent>
    </complexType>
   
    <complexType name="Orange">
        <complexContent>
            <extension base="base:Fruit">
            </extension>
        </complexContent>
    </complexType>
</schema>

My question is:
1) In order to correctly marshall/unmarshall JSON request/response using Jersey and its client API, which JSON notation (mapped, mappedJettison, badgerFish, natual) should I use in this case (with multiple namespaces in schema)? It seems only mappedJettison notation can be used as I did a simple search in the mail list archive, but I am not sure.

2) I implemented a JAXBContextResolver and tried mappedJettison notation:
public JAXBContextResolver() throws Exception {
        Map<String, String> namespaceMap = new HashMap<String, String>();
        namespaceMap.put("http://www.w3.org/2001/XMLSchema", "xs");
        namespaceMap.put("http://www.w3.org/2001/XMLSchema-instance", "xsi");
        namespaceMap.put("http://fruitbase.example.org", "base");
        namespaceMap.put("http://fruits.example.org", "fruits");
        JSONConfiguration config = JSONConfiguration.mappedJettison().xml2JsonNs(namespaceMap).build();
        this.m_context = new JSONJAXBContext(
                config,
                m_types);
    }
But  in the JSON response, I found JAXB used a random prefix (ns2) for QName in attribute values:
{"base.fruits":{"base.fruit":{"@xsi.type":"ns2:Apple","base.name":"apple","base.color":"red","fruits.weight":2}}}
Is it a bug for Jersey? I know it is possible to change that behavior via JAXB API (https://jaxb.dev.java.net/guide/Changing_prefixes.html), but it is wrapped by Jersey, and how can I control that in Jersey?

I attached a zipped maven project, which contains detailed implementation and test case for my issue. Thanks in advance for all your help.

Environment:
Jersey 1.0.3
Java 1.5

Regards,
Ni Yue


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

jersey-json-sample.zip (34K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: JSON Unmarshalling Issue

Jakub Podlesak
Hi Ni,

Ni Yue wrote:

> Hello,
>
> I am using Jersey to serve JSON response and met some issue. In my
> case, I used JAXB for XML marshalling and used Jersey's build-in
> function to map XML to JSON. And there're multiple namespaces in my
> XML schema, for example:
> *
> base.xsd:*
>
>     <?xml version="1.0" encoding="UTF-8"?>
>     <schema
>         xmlns="http://www.w3.org/2001/XMLSchema"
>         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>         xmlns:base="http://fruitbase.example.org"
>         targetNamespace="http://fruitbase.example.org"
>         elementFormDefault="qualified">
>        
>         <element name="fruits">
>             <complexType>
>                 <sequence>
>                     <element name="fruit" type="base:Fruit"
>     minOccurs="0"></element>
>                 </sequence>
>             </complexType>
>         </element>
>        
>         <complexType name="Fruit">
>             <sequence>
>                 <element name="name" type="string"/>
>                 <element name="color" type="string"/>
>             </sequence>
>         </complexType>
>     </schema>
>
>
> *fruits.xsd:*
>
>     <?xml version="1.0" encoding="UTF-8"?>
>     <schema
>         xmlns="http://www.w3.org/2001/XMLSchema"
>         xmlns:base="http://fruitbase.example.org"
>         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>         xmlns:fruits="http://fruits.example.org"
>         targetNamespace="http://fruits.example.org"
>         elementFormDefault="qualified">
>         <import namespace="http://fruitbase.example.org"
>     schemaLocation="base.xsd"></import>
>         <complexType name="Apple">
>             <complexContent>
>                 <extension base="base:Fruit">
>                     <sequence>
>                         <element name="weight" type="int"></element>
>                     </sequence>
>                     <anyAttribute/>
>                 </extension>
>             </complexContent>
>         </complexType>
>        
>         <complexType name="Orange">
>             <complexContent>
>                 <extension base="base:Fruit">
>                 </extension>
>             </complexContent>
>         </complexType>
>     </schema>
>
>
> My question is:
> 1) In order to correctly marshall/unmarshall JSON request/response
> using Jersey and its client API, which JSON notation (mapped,
> mappedJettison, badgerFish, natual) should I use in this case (with
> multiple namespaces in schema)? It seems only mappedJettison notation
> can be used as I did a simple search in the mail list archive, but I
> am not sure.

It should be supported for both Jettison based notations (Jettison
mapped and BadgerFish),
where for the Badgerfish, the thing (namespace handling) should work out
of the box, without a need of any special
configuration, while when using the Jettison mapped notation, you would
need to explicitly
configure the namespace mapping (see
https://jersey.dev.java.net/documentation/1.1.0-ea/user-guide.html#d4e603 
for details)

>
> 2) I implemented a JAXBContextResolver and tried mappedJettison notation:
>
>     public JAXBContextResolver() throws Exception {
>             Map<String, String> namespaceMap = new HashMap<String,
>     String>();
>             namespaceMap.put("http://www.w3.org/2001/XMLSchema", "xs");
>            
>     namespaceMap.put("http://www.w3.org/2001/XMLSchema-instance", "xsi");
>             namespaceMap.put("http://fruitbase.example.org", "base");
>             namespaceMap.put("http://fruits.example.org", "fruits");
>             JSONConfiguration config =
>     JSONConfiguration.mappedJettison().xml2JsonNs(namespaceMap).build();
>             this.m_context = new JSONJAXBContext(
>                     config,
>                     m_types);
>         }
>
> But  in the JSON response, I found JAXB used a random prefix (ns2) for
> QName in attribute values:
>
>     {"base.fruits":{"base.fruit":{"@xsi.type":"*ns2:Apple*","base.name <http://base.name>":"apple","base.color":"red","fruits.weight":2}}}
>
> Is it a bug for Jersey? I know it is possible to change that behavior
> via JAXB API (https://jaxb.dev.java.net/guide/Changing_prefixes.html),
> but it is wrapped by Jersey, and how can I control that in Jersey?

You would need to implement a JAXB NamespacePrefixMapper (see
http://blogs.sun.com/enterprisetechtips/resource/JAXBSample.java) and
hand it over to the actual Marshaller.
It is now not possible to do so out-of-the-box right now, but it is a
great idea to have such a feature in place.
Could you please file a feature request, so that i can work on this at
the after JavaOne timeframe?

Thanks,

~Jakub

>
> I attached a zipped maven project, which contains detailed
> implementation and test case for my issue. Thanks in advance for all
> your help.
>
> Environment:
> Jersey 1.0.3
> Java 1.5
>
> Regards,
> Ni Yue
>
> ------------------------------------------------------------------------
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>  


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: JSON Unmarshalling Issue

Ni Yue
Hi Jakub,

I filed a feature request for that:
https://jersey.dev.java.net/issues/show_bug.cgi?id=301

And for badgerFish notation, I changed my test to use badgerFish notation, but still can not get it to work.
I got a JSON response (in the browser):

{"fruits":{"@xmlns":{"ns2":"http:\/\/fruits.example.org","$":"http:\/\/fruitbase.example.org"},"fruit":{"@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance"},"@xsi:type":"ns2:Apple","name":{"$":"apple"},"color":{"$":"red"},"ns2:weight":{"$":"2"}}}}

Although "ns2" is specified as a prefix for namespace "http://fruits.example.org" in response, but it still failed to be unmarshalled in client side with the error message:
javax.ws.rs.WebApplicationException: javax.xml.bind.UnmarshalException
 - with linked exception:
[javax.xml.stream.XMLStreamException: Invalid prefix ns2 on element ns2:weight]

Do you have any idea what's the problem here? You can change my JAXBContextResolver in attached maven project to use badgerFish notation to reproduce this issue. Thanks.

Here's the full stack trace printed in the client side:
javax.ws.rs.WebApplicationException: javax.xml.bind.UnmarshalException
 - with linked exception:
[javax.xml.stream.XMLStreamException: Invalid prefix ns2 on element ns2:weight]
    at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:99)
    at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:259)
    at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:220)
    at com.sun.jersey.api.client.WebResource.handle(WebResource.java:561)
    at com.sun.jersey.api.client.WebResource.get(WebResource.java:179)
    at org.example.JsonTest.testJsonResponse(JsonTest.java:16)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at junit.framework.TestCase.runTest(TestCase.java:164)
    at junit.framework.TestCase.runBare(TestCase.java:130)
    at junit.framework.TestResult$1.protect(TestResult.java:106)
    at junit.framework.TestResult.runProtected(TestResult.java:124)
    at junit.framework.TestResult.run(TestResult.java:109)
    at junit.framework.TestCase.run(TestCase.java:120)
    at junit.framework.TestSuite.runTest(TestSuite.java:230)
    at junit.framework.TestSuite.run(TestSuite.java:225)
    at org.junit.internal.runners.OldTestClassRunner.run(OldTestClassRunner.java:76)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: javax.xml.bind.UnmarshalException
 - with linked exception:
[javax.xml.stream.XMLStreamException: Invalid prefix ns2 on element ns2:weight]
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(UnmarshallerImpl.java:426)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:362)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:339)
    at com.sun.jersey.json.impl.JSONUnmarshaller.unmarshal(JSONUnmarshaller.java:100)
    at com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider.readFrom(JSONRootElementProvider.java:105)
    at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:97)
    ... 24 more
Caused by: javax.xml.stream.XMLStreamException: Invalid prefix ns2 on element ns2:weight
    at org.codehaus.jettison.badgerfish.BadgerFishConvention.createQName(BadgerFishConvention.java:76)
    at org.codehaus.jettison.Node.<init>(Node.java:55)
    at org.codehaus.jettison.badgerfish.BadgerFishXMLStreamReader.processKey(BadgerFishXMLStreamReader.java:100)
    at org.codehaus.jettison.badgerfish.BadgerFishXMLStreamReader.processElement(BadgerFishXMLStreamReader.java:87)
    at org.codehaus.jettison.badgerfish.BadgerFishXMLStreamReader.next(BadgerFishXMLStreamReader.java:67)
    at com.sun.xml.bind.v2.runtime.unmarshaller.StAXStreamConnector.bridge(StAXStreamConnector.java:192)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:360)
    ... 28 more

Regards,
Ni Yue

2009/6/2 Jakub Podlesak <[hidden email]>
Hi Ni,


Ni Yue wrote:
Hello,

I am using Jersey to serve JSON response and met some issue. In my case, I used JAXB for XML marshalling and used Jersey's build-in function to map XML to JSON. And there're multiple namespaces in my XML schema, for example:
*
base.xsd:*

   <?xml version="1.0" encoding="UTF-8"?>
   <schema
       xmlns="http://www.w3.org/2001/XMLSchema"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:base="http://fruitbase.example.org"
       targetNamespace="http://fruitbase.example.org"
       elementFormDefault="qualified">
             <element name="fruits">
           <complexType>
               <sequence>
                   <element name="fruit" type="base:Fruit"
   minOccurs="0"></element>
               </sequence>
           </complexType>
       </element>
             <complexType name="Fruit">
           <sequence>
               <element name="name" type="string"/>
               <element name="color" type="string"/>
           </sequence>
       </complexType>
   </schema>


*fruits.xsd:*

   <?xml version="1.0" encoding="UTF-8"?>
   <schema
       xmlns="http://www.w3.org/2001/XMLSchema"
       xmlns:base="http://fruitbase.example.org"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:fruits="http://fruits.example.org"
       targetNamespace="http://fruits.example.org"
       elementFormDefault="qualified">
       <import namespace="http://fruitbase.example.org"
   schemaLocation="base.xsd"></import>
       <complexType name="Apple">
           <complexContent>
               <extension base="base:Fruit">
                   <sequence>
                       <element name="weight" type="int"></element>
                   </sequence>
                   <anyAttribute/>
               </extension>
           </complexContent>
       </complexType>
             <complexType name="Orange">
           <complexContent>
               <extension base="base:Fruit">
               </extension>
           </complexContent>
       </complexType>
   </schema>


My question is:
1) In order to correctly marshall/unmarshall JSON request/response using Jersey and its client API, which JSON notation (mapped, mappedJettison, badgerFish, natual) should I use in this case (with multiple namespaces in schema)? It seems only mappedJettison notation can be used as I did a simple search in the mail list archive, but I am not sure.

It should be supported for both Jettison based notations (Jettison mapped and BadgerFish),
where for the Badgerfish, the thing (namespace handling) should work out of the box, without a need of any special
configuration, while when using the Jettison mapped notation, you would need to explicitly
configure the namespace mapping (see https://jersey.dev.java.net/documentation/1.1.0-ea/user-guide.html#d4e603 for details)


2) I implemented a JAXBContextResolver and tried mappedJettison notation:

   public JAXBContextResolver() throws Exception {
           Map<String, String> namespaceMap = new HashMap<String,
   String>();
           namespaceMap.put("http://www.w3.org/2001/XMLSchema", "xs");
             namespaceMap.put("http://www.w3.org/2001/XMLSchema-instance", "xsi");
           namespaceMap.put("http://fruitbase.example.org", "base");
           namespaceMap.put("http://fruits.example.org", "fruits");
           JSONConfiguration config =
   JSONConfiguration.mappedJettison().xml2JsonNs(namespaceMap).build();
           this.m_context = new JSONJAXBContext(
                   config,
                   m_types);
       }

But  in the JSON response, I found JAXB used a random prefix (ns2) for QName in attribute values:

   {"base.fruits":{"base.fruit":{"@xsi.type":"*ns2:Apple*","base.name <http://base.name>":"apple","base.color":"red","fruits.weight":2}}}


Is it a bug for Jersey? I know it is possible to change that behavior via JAXB API (https://jaxb.dev.java.net/guide/Changing_prefixes.html), but it is wrapped by Jersey, and how can I control that in Jersey?

You would need to implement a JAXB NamespacePrefixMapper (see http://blogs.sun.com/enterprisetechtips/resource/JAXBSample.java) and hand it over to the actual Marshaller.
It is now not possible to do so out-of-the-box right now, but it is a great idea to have such a feature in place.
Could you please file a feature request, so that i can work on this at the after JavaOne timeframe?

Thanks,

~Jakub

I attached a zipped maven project, which contains detailed implementation and test case for my issue. Thanks in advance for all your help.

Environment:
Jersey 1.0.3
Java 1.5

Regards,
Ni Yue

------------------------------------------------------------------------

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: JSON Unmarshalling Issue

Jakub Podlesak
Ni Yue wrote:
> Hi Jakub,
>
> I filed a feature request for that:
> https://jersey.dev.java.net/issues/show_bug.cgi?id=301

Thanks,

>
> And for badgerFish notation, I changed my test to use badgerFish
> notation, but still can not get it to work.
> I got a JSON response (in the browser):
>
>     {"fruits":{"@xmlns":{"ns2":"http:\/\/fruits.example.org
>     <http://fruits.example.org>","$":"http:\/\/fruitbase.example.org
>     <http://fruitbase.example.org>"},"fruit":{"@xmlns":{"xsi":"http:\/\/www.w3.org
>     <http://www.w3.org>\/2001\/XMLSchema-instance"},"@xsi:type":"ns2:Apple","name":{"$":"apple"},"color":{"$":"red"},"ns2:weight":{"$":"2"}}}}
>
>
> Although "ns2" is specified as a prefix for namespace
> "http://fruits.example.org" in response, but it still failed to be
> unmarshalled in client side with the error message:
>
>     javax.ws.rs.WebApplicationException: javax.xml.bind.UnmarshalException
>      - with linked exception:
>     [javax.xml.stream.XMLStreamException: Invalid prefix ns2 on
>     element ns2:weight]
>
>
> Do you have any idea what's the problem here? You can change my
> JAXBContextResolver in attached maven project to use badgerFish
> notation to reproduce this issue. Thanks.
I will try to find some time, hopefully today, to look at this. If i do
not follow up, please bear with me, as i am attending
JavaOne and taking a week off right after the conference finishes. Then
i will respond once i am back at the office
in the week of June 15th.

Thanks for understanding,

~Jakub

>
> Here's the full stack trace printed in the client side:
> javax.ws.rs.WebApplicationException: javax.xml.bind.UnmarshalException
>  - with linked exception:
> [javax.xml.stream.XMLStreamException: Invalid prefix ns2 on element
> ns2:weight]
>     at
> com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:99)
>     at
> com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:259)
>     at
> com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:220)
>     at com.sun.jersey.api.client.WebResource.handle(WebResource.java:561)
>     at com.sun.jersey.api.client.WebResource.get(WebResource.java:179)
>     at org.example.JsonTest.testJsonResponse(JsonTest.java:16)
>     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>     at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>     at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>     at java.lang.reflect.Method.invoke(Method.java:585)
>     at junit.framework.TestCase.runTest(TestCase.java:164)
>     at junit.framework.TestCase.runBare(TestCase.java:130)
>     at junit.framework.TestResult$1.protect(TestResult.java:106)
>     at junit.framework.TestResult.runProtected(TestResult.java:124)
>     at junit.framework.TestResult.run(TestResult.java:109)
>     at junit.framework.TestCase.run(TestCase.java:120)
>     at junit.framework.TestSuite.runTest(TestSuite.java:230)
>     at junit.framework.TestSuite.run(TestSuite.java:225)
>     at
> org.junit.internal.runners.OldTestClassRunner.run(OldTestClassRunner.java:76)
>     at
> org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
>     at
> org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
>     at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
>     at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
>     at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
>     at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
> Caused by: javax.xml.bind.UnmarshalException
>  - with linked exception:
> [javax.xml.stream.XMLStreamException: Invalid prefix ns2 on element
> ns2:weight]
>     at
> com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(UnmarshallerImpl.java:426)
>     at
> com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:362)
>     at
> com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:339)
>     at
> com.sun.jersey.json.impl.JSONUnmarshaller.unmarshal(JSONUnmarshaller.java:100)
>     at
> com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider.readFrom(JSONRootElementProvider.java:105)
>     at
> com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:97)
>     ... 24 more
> Caused by: javax.xml.stream.XMLStreamException: Invalid prefix ns2 on
> element ns2:weight
>     at
> org.codehaus.jettison.badgerfish.BadgerFishConvention.createQName(BadgerFishConvention.java:76)
>     at org.codehaus.jettison.Node.<init>(Node.java:55)
>     at
> org.codehaus.jettison.badgerfish.BadgerFishXMLStreamReader.processKey(BadgerFishXMLStreamReader.java:100)
>     at
> org.codehaus.jettison.badgerfish.BadgerFishXMLStreamReader.processElement(BadgerFishXMLStreamReader.java:87)
>     at
> org.codehaus.jettison.badgerfish.BadgerFishXMLStreamReader.next(BadgerFishXMLStreamReader.java:67)
>     at
> com.sun.xml.bind.v2.runtime.unmarshaller.StAXStreamConnector.bridge(StAXStreamConnector.java:192)
>     at
> com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:360)
>     ... 28 more
>
> Regards,
> Ni Yue
>
> 2009/6/2 Jakub Podlesak <[hidden email]
> <mailto:[hidden email]>>
>
>     Hi Ni,
>
>
>     Ni Yue wrote:
>
>         Hello,
>
>         I am using Jersey to serve JSON response and met some issue.
>         In my case, I used JAXB for XML marshalling and used Jersey's
>         build-in function to map XML to JSON. And there're multiple
>         namespaces in my XML schema, for example:
>         *
>         base.xsd:*
>
>            <?xml version="1.0" encoding="UTF-8"?>
>            <schema
>                xmlns="http://www.w3.org/2001/XMLSchema"
>                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>                xmlns:base="http://fruitbase.example.org"
>                targetNamespace="http://fruitbase.example.org"
>                elementFormDefault="qualified">
>                      <element name="fruits">
>                    <complexType>
>                        <sequence>
>                            <element name="fruit" type="base:Fruit"
>            minOccurs="0"></element>
>                        </sequence>
>                    </complexType>
>                </element>
>                      <complexType name="Fruit">
>                    <sequence>
>                        <element name="name" type="string"/>
>                        <element name="color" type="string"/>
>                    </sequence>
>                </complexType>
>            </schema>
>
>
>         *fruits.xsd:*
>
>            <?xml version="1.0" encoding="UTF-8"?>
>            <schema
>                xmlns="http://www.w3.org/2001/XMLSchema"
>                xmlns:base="http://fruitbase.example.org"
>                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>                xmlns:fruits="http://fruits.example.org"
>                targetNamespace="http://fruits.example.org"
>                elementFormDefault="qualified">
>                <import namespace="http://fruitbase.example.org"
>            schemaLocation="base.xsd"></import>
>                <complexType name="Apple">
>                    <complexContent>
>                        <extension base="base:Fruit">
>                            <sequence>
>                                <element name="weight"
>         type="int"></element>
>                            </sequence>
>                            <anyAttribute/>
>                        </extension>
>                    </complexContent>
>                </complexType>
>                      <complexType name="Orange">
>                    <complexContent>
>                        <extension base="base:Fruit">
>                        </extension>
>                    </complexContent>
>                </complexType>
>            </schema>
>
>
>         My question is:
>         1) In order to correctly marshall/unmarshall JSON
>         request/response using Jersey and its client API, which JSON
>         notation (mapped, mappedJettison, badgerFish, natual) should I
>         use in this case (with multiple namespaces in schema)? It
>         seems only mappedJettison notation can be used as I did a
>         simple search in the mail list archive, but I am not sure.
>
>
>     It should be supported for both Jettison based notations (Jettison
>     mapped and BadgerFish),
>     where for the Badgerfish, the thing (namespace handling) should
>     work out of the box, without a need of any special
>     configuration, while when using the Jettison mapped notation, you
>     would need to explicitly
>     configure the namespace mapping (see
>     https://jersey.dev.java.net/documentation/1.1.0-ea/user-guide.html#d4e603
>     for details)
>
>
>         2) I implemented a JAXBContextResolver and tried
>         mappedJettison notation:
>
>            public JAXBContextResolver() throws Exception {
>                    Map<String, String> namespaceMap = new HashMap<String,
>            String>();
>                  
>          namespaceMap.put("http://www.w3.org/2001/XMLSchema", "xs");
>                    
>          namespaceMap.put("http://www.w3.org/2001/XMLSchema-instance",
>         "xsi");
>                    namespaceMap.put("http://fruitbase.example.org",
>         "base");
>                    namespaceMap.put("http://fruits.example.org",
>         "fruits");
>                    JSONConfiguration config =
>          
>          JSONConfiguration.mappedJettison().xml2JsonNs(namespaceMap).build();
>                    this.m_context = new JSONJAXBContext(
>                            config,
>                            m_types);
>                }
>
>         But  in the JSON response, I found JAXB used a random prefix
>         (ns2) for QName in attribute values:
>
>          
>          {"base.fruits":{"base.fruit":{"@xsi.type":"*ns2:Apple*","base.name
>         <http://base.name>
>         <http://base.name>":"apple","base.color":"red","fruits.weight":2}}}
>
>
>
>         Is it a bug for Jersey? I know it is possible to change that
>         behavior via JAXB API
>         (https://jaxb.dev.java.net/guide/Changing_prefixes.html), but
>         it is wrapped by Jersey, and how can I control that in Jersey?
>
>
>     You would need to implement a JAXB NamespacePrefixMapper (see
>     http://blogs.sun.com/enterprisetechtips/resource/JAXBSample.java)
>     and hand it over to the actual Marshaller.
>     It is now not possible to do so out-of-the-box right now, but it
>     is a great idea to have such a feature in place.
>     Could you please file a feature request, so that i can work on
>     this at the after JavaOne timeframe?
>
>     Thanks,
>
>     ~Jakub
>
>
>         I attached a zipped maven project, which contains detailed
>         implementation and test case for my issue. Thanks in advance
>         for all your help.
>
>         Environment:
>         Jersey 1.0.3
>         Java 1.5
>
>         Regards,
>         Ni Yue
>
>         ------------------------------------------------------------------------
>
>         ---------------------------------------------------------------------
>         To unsubscribe, e-mail: [hidden email]
>         <mailto:[hidden email]>
>         For additional commands, e-mail:
>         [hidden email]
>         <mailto:[hidden email]>
>          
>
>
>
>     ---------------------------------------------------------------------
>     To unsubscribe, e-mail: [hidden email]
>     <mailto:[hidden email]>
>     For additional commands, e-mail: [hidden email]
>     <mailto:[hidden email]>
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: JSON Unmarshalling Issue

Ni Yue
That's ok, and please have a try on mappedJettison notation because I found even if I implemented the feature request 301 locally, the mappedJettison notation will fail with similar error with badgerFish notation. Thanks for your help.

2009/6/4 Jakub Podlesak <[hidden email]>
Ni Yue wrote:
Hi Jakub,

I filed a feature request for that:
https://jersey.dev.java.net/issues/show_bug.cgi?id=301

Thanks,


And for badgerFish notation, I changed my test to use badgerFish notation, but still can not get it to work.
I got a JSON response (in the browser):

   {"fruits":{"@xmlns":{"ns2":"http:\/\/fruits.example.org
   <http://fruits.example.org>","$":"http:\/\/fruitbase.example.org

   <http://fruitbase.example.org>"},"fruit":{"@xmlns":{"xsi":"http:\/\/www.w3.org
   <http://www.w3.org>\/2001\/XMLSchema-instance"},"@xsi:type":"ns2:Apple","name":{"$":"apple"},"color":{"$":"red"},"ns2:weight":{"$":"2"}}}}


Although "ns2" is specified as a prefix for namespace "http://fruits.example.org" in response, but it still failed to be unmarshalled in client side with the error message:

   javax.ws.rs.WebApplicationException: javax.xml.bind.UnmarshalException
    - with linked exception:
   [javax.xml.stream.XMLStreamException: Invalid prefix ns2 on
   element ns2:weight]


Do you have any idea what's the problem here? You can change my JAXBContextResolver in attached maven project to use badgerFish notation to reproduce this issue. Thanks.
I will try to find some time, hopefully today, to look at this. If i do not follow up, please bear with me, as i am attending
JavaOne and taking a week off right after the conference finishes. Then i will respond once i am back at the office
in the week of June 15th.

Thanks for understanding,

~Jakub


Here's the full stack trace printed in the client side:
javax.ws.rs.WebApplicationException: javax.xml.bind.UnmarshalException
 - with linked exception:
[javax.xml.stream.XMLStreamException: Invalid prefix ns2 on element ns2:weight]
   at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:99)
   at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:259)
   at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:220)
   at com.sun.jersey.api.client.WebResource.handle(WebResource.java:561)
   at com.sun.jersey.api.client.WebResource.get(WebResource.java:179)
   at org.example.JsonTest.testJsonResponse(JsonTest.java:16)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:585)
   at junit.framework.TestCase.runTest(TestCase.java:164)
   at junit.framework.TestCase.runBare(TestCase.java:130)
   at junit.framework.TestResult$1.protect(TestResult.java:106)
   at junit.framework.TestResult.runProtected(TestResult.java:124)
   at junit.framework.TestResult.run(TestResult.java:109)
   at junit.framework.TestCase.run(TestCase.java:120)
   at junit.framework.TestSuite.runTest(TestSuite.java:230)
   at junit.framework.TestSuite.run(TestSuite.java:225)
   at org.junit.internal.runners.OldTestClassRunner.run(OldTestClassRunner.java:76)
   at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
   at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: javax.xml.bind.UnmarshalException
 - with linked exception:
[javax.xml.stream.XMLStreamException: Invalid prefix ns2 on element ns2:weight]
   at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(UnmarshallerImpl.java:426)
   at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:362)
   at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:339)
   at com.sun.jersey.json.impl.JSONUnmarshaller.unmarshal(JSONUnmarshaller.java:100)
   at com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider.readFrom(JSONRootElementProvider.java:105)
   at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:97)
   ... 24 more
Caused by: javax.xml.stream.XMLStreamException: Invalid prefix ns2 on element ns2:weight
   at org.codehaus.jettison.badgerfish.BadgerFishConvention.createQName(BadgerFishConvention.java:76)
   at org.codehaus.jettison.Node.<init>(Node.java:55)
   at org.codehaus.jettison.badgerfish.BadgerFishXMLStreamReader.processKey(BadgerFishXMLStreamReader.java:100)
   at org.codehaus.jettison.badgerfish.BadgerFishXMLStreamReader.processElement(BadgerFishXMLStreamReader.java:87)
   at org.codehaus.jettison.badgerfish.BadgerFishXMLStreamReader.next(BadgerFishXMLStreamReader.java:67)
   at com.sun.xml.bind.v2.runtime.unmarshaller.StAXStreamConnector.bridge(StAXStreamConnector.java:192)
   at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:360)
   ... 28 more

Regards,
Ni Yue

2009/6/2 Jakub Podlesak <[hidden email] <mailto:[hidden email]>>


   Hi Ni,


   Ni Yue wrote:

       Hello,

       I am using Jersey to serve JSON response and met some issue.
       In my case, I used JAXB for XML marshalling and used Jersey's
       build-in function to map XML to JSON. And there're multiple
       namespaces in my XML schema, for example:
       *
       base.xsd:*

          <?xml version="1.0" encoding="UTF-8"?>
          <schema
              xmlns="http://www.w3.org/2001/XMLSchema"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns:base="http://fruitbase.example.org"
              targetNamespace="http://fruitbase.example.org"
              elementFormDefault="qualified">
                    <element name="fruits">
                  <complexType>
                      <sequence>
                          <element name="fruit" type="base:Fruit"
          minOccurs="0"></element>
                      </sequence>
                  </complexType>
              </element>
                    <complexType name="Fruit">
                  <sequence>
                      <element name="name" type="string"/>
                      <element name="color" type="string"/>
                  </sequence>
              </complexType>
          </schema>


       *fruits.xsd:*

          <?xml version="1.0" encoding="UTF-8"?>
          <schema
              xmlns="http://www.w3.org/2001/XMLSchema"
              xmlns:base="http://fruitbase.example.org"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns:fruits="http://fruits.example.org"
              targetNamespace="http://fruits.example.org"
              elementFormDefault="qualified">
              <import namespace="http://fruitbase.example.org"
          schemaLocation="base.xsd"></import>
              <complexType name="Apple">
                  <complexContent>
                      <extension base="base:Fruit">
                          <sequence>
                              <element name="weight"
       type="int"></element>
                          </sequence>
                          <anyAttribute/>
                      </extension>
                  </complexContent>
              </complexType>
                    <complexType name="Orange">
                  <complexContent>
                      <extension base="base:Fruit">
                      </extension>
                  </complexContent>
              </complexType>
          </schema>


       My question is:
       1) In order to correctly marshall/unmarshall JSON
       request/response using Jersey and its client API, which JSON
       notation (mapped, mappedJettison, badgerFish, natual) should I
       use in this case (with multiple namespaces in schema)? It
       seems only mappedJettison notation can be used as I did a
       simple search in the mail list archive, but I am not sure.


   It should be supported for both Jettison based notations (Jettison
   mapped and BadgerFish),
   where for the Badgerfish, the thing (namespace handling) should
   work out of the box, without a need of any special
   configuration, while when using the Jettison mapped notation, you
   would need to explicitly
   configure the namespace mapping (see
   https://jersey.dev.java.net/documentation/1.1.0-ea/user-guide.html#d4e603
   for details)


       2) I implemented a JAXBContextResolver and tried
       mappedJettison notation:

          public JAXBContextResolver() throws Exception {
                  Map<String, String> namespaceMap = new HashMap<String,
          String>();
                        namespaceMap.put("http://www.w3.org/2001/XMLSchema", "xs");
                          namespaceMap.put("http://www.w3.org/2001/XMLSchema-instance",
       "xsi");
                  namespaceMap.put("http://fruitbase.example.org",
       "base");
                  namespaceMap.put("http://fruits.example.org",
       "fruits");
                  JSONConfiguration config =
                JSONConfiguration.mappedJettison().xml2JsonNs(namespaceMap).build();
                  this.m_context = new JSONJAXBContext(
                          config,
                          m_types);
              }

       But  in the JSON response, I found JAXB used a random prefix
       (ns2) for QName in attribute values:

                {"base.fruits":{"base.fruit":{"@xsi.type":"*ns2:Apple*","base.name
       <http://base.name>
       <http://base.name>":"apple","base.color":"red","fruits.weight":2}}}



       Is it a bug for Jersey? I know it is possible to change that
       behavior via JAXB API
       (https://jaxb.dev.java.net/guide/Changing_prefixes.html), but
       it is wrapped by Jersey, and how can I control that in Jersey?


   You would need to implement a JAXB NamespacePrefixMapper (see
   http://blogs.sun.com/enterprisetechtips/resource/JAXBSample.java)
   and hand it over to the actual Marshaller.
   It is now not possible to do so out-of-the-box right now, but it
   is a great idea to have such a feature in place.
   Could you please file a feature request, so that i can work on
   this at the after JavaOne timeframe?

   Thanks,

   ~Jakub


       I attached a zipped maven project, which contains detailed
       implementation and test case for my issue. Thanks in advance
       for all your help.

       Environment:
       Jersey 1.0.3
       Java 1.5

       Regards,
       Ni Yue

       ------------------------------------------------------------------------

       ---------------------------------------------------------------------
       To unsubscribe, e-mail: [hidden email]
       <mailto:[hidden email]>

       For additional commands, e-mail:
       [hidden email]
       <mailto:[hidden email]>

       


   ---------------------------------------------------------------------
   To unsubscribe, e-mail: [hidden email]
   <mailto:[hidden email]>

   For additional commands, e-mail: [hidden email]
   <mailto:[hidden email]>




---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]