users@jersey.java.net

Re: [WARNING : A/V UNSCANNABLE] RE: parsing JSON with Arrays using Jettison

From: Jakub Podlesak <jakub.podlesak_at_oracle.com>
Date: Mon, 22 Nov 2010 11:26:26 +0100

Great! I am glad you have found a solution.

~Jakub

On 11/22/2010 06:19 AM, Dhanush Gopinath wrote:
> Thanks Jakub. I figured out it was a bug in Jettison, and I fixed it by writing my own UnMarshaller implementation
>
> Your suggestion also works. May be should try it out too, but the problem here is that I am depended on JAXB classes created by a different team. So whenever they change the names of arrays, I will have to change mine. But if any bugs happen with my Unmarshaller Impl, I do have a solution to fallback. Many thanks for that.
>
> Regards
> Dhanush
>
> -----Original Message-----
> From: Jakub Podlesak [mailto:jakub.podlesak_at_oracle.com]
> Sent: Friday, November 19, 2010 8:21 PM
> To: Dhanush Gopinath
> Cc: users_at_jersey.java.net
> Subject: Re: [WARNING : A/V UNSCANNABLE] RE: parsing JSON with Arrays using Jettison
>
> Hi Dhanush,
>
> this seems to be a bug in Jettison :-(
>
> try to update your com.theserverlabs.namespaces.cars.JAXBContextResolver
> so that it uses the following JSONConfiguration:
>
> JSONConfiguration.mapped().rootUnwrapping(false).arrays("1.vehicle").xml2JsonNs(ns2json).build()
>
> then the thing should work fine.
>
> You can also get less talkaltive representation with:
>
> JSONConfiguration.mapped().arrays("1.vehicle").xml2JsonNs(ns2json).build()
>
> HTH,
>
> ~Jakub
>
> [1]http://jersey.java.net/nonav/documentation/latest/json.html#d0e1960
>
> On 11/19/2010 09:56 AM, Dhanush Gopinath wrote:
>> Hi Jakub,
>>
>> The JSON representation looks like how it should be with [ ] brackets
>> put in when more than one element is there. I have attached the app as
>> an Eclipse project along with the mail. Please look at these two methods
>> in the class com.altair.test.CarService
>>
>> @GET
>>
>> @Path("getVehicles")
>>
>> @Produces({MediaType./APPLICATION_JSON/, MediaType./APPLICATION_XML/})
>>
>> *public*JAXBElement<VehicleObjList> getVehicles(
>>
>> @POST
>>
>> @Path("putVehicles")
>>
>> @Produces(MediaType./TEXT_PLAIN/)
>>
>> @Consumes({MediaType./APPLICATION_JSON/, MediaType./APPLICATION_XML/})
>>
>> *public*String putVehicles(JAXBElement<VehicleObjList> element)
>>
>> I am getting an output from getVehicles and then posting it to the put
>> vehicles method.
>>
>> This is the input for my POST
>>
>> {"1.vehicleList":{"1.vehicle":*[*{"1.car":{"@price":"200","@model":"2010","@make":"Punto","@id":"1"},"1.carObj":{"1.name":"Punto","1.year":789,"1.company":"Fiat"},"1.busObj":{"1.busName":"ashok","1.year":789,"1.buscompany":"Lyland"}},{"1.car":{"@price":"200","@model":"2010","@make":"Punto","@id":"1"},"1.carObj":{"1.name":"Punto","1.year":789,"1.company":"Fiat"},"1.busObj":{"1.busName":"ashok","1.year":789,"1.buscompany":"Lyland"}},{"1.car":{"@price":"200","@model":"2010","@make":"Punto","@id":"1"},"1.carObj":{"1.name":"Punto","1.year":789,"1.company":"Fiat"},"1.busObj":{"1.busName":"ashok","1.year":789,"1.buscompany":"Lyland"}}*]*}}
>>
>> It hits putVehicles method here:
>>
>> VehicleObjList list = element.getValue();
>>
>> List<VehicleObj> vehicle = list.getVehicle(); --ąTHIS RETURNS EMPTY
>>
>> Now change the input to the POST and give only one element in the Array
>>
>> {"1.vehicleList":{"1.vehicle":{"1.car":{"@price":"200","@model":"2010","@make":"Punto","@id":"1"},"1.carObj":{"1.name":"Punto","1.year":789,"1.company":"Fiat"},"1.busObj":{"1.busName":"ashok","1.year":789,"1.buscompany":"Lyland"}}
>>
>> }}
>>
>> Then the List<VehicleObj> is populated with one element.
>>
>> Hope this helps.
>>
>> Thanks
>>
>> Dhanush
>>
>> ------------------------------------------------------------------------
>>
>> *From:*Jakub Podlesak [mailto:jakub.podlesak_at_oracle.com]
>> *Sent:* Thursday, November 18, 2010 8:00 PM
>> *To:* users_at_jersey.java.net
>> *Cc:* Dhanush Gopinath
>> *Subject:* Re: parsing JSON with Arrays using Jettison
>>
>>
>> Hi Dhanush,
>>
>> If you get the list (containing more than 1 item), how the JSON
>> representation looks like?
>>
>> Would you be able to send a reproducible test case? I mean a whole
>> simple app?
>>
>> Thanks,
>>
>> ~Jakub
>>
>>
>> On 11/12/2010 01:44 PM, Dhanush Gopinath wrote:
>>
>> Hi,
>>
>> I have a REST service which has a get method and post method. Get method
>> returns a JAXBElement< of some object> which contains an Array of other
>> Objects. Where as POST method receives the same JAXBElement< of some
>> object> with an Array of other Objects. I am using Jettison mapping as
>> the JSONConfiguration.
>>
>> The GET operation works fine and I get the correct JSON values when I
>> accept JSON. But when posting the same JSON back using the POST method,
>> it doesn't populate the Array of Objects inside the JAXBElement.
>>
>> The POST works fine when the array size is 1; if there is more than one
>> element then the JAXBElement always has null as the Array value.
>>
>> Any idea why this is happening.
>>
>> Here are my REST API's
>>
>> @GET
>>
>> @Path("getVehicles")
>>
>> @Produces({MediaType./APPLICATION_JSON/, MediaType./APPLICATION_XML/})
>>
>> *public*JAXBElement<VehicleObjList> getVehicles()
>>
>> {
>>
>> CarType car = *new*CarType();
>>
>> car.setMake("Punto");
>>
>> car.setId(1);
>>
>> car.setModel("2010");
>>
>> car.setPrice(200);
>>
>> BusObject bo = *new*BusObject();
>>
>> bo.setBuscompany("Lyland");
>>
>> bo.setBusName("ashok");
>>
>> bo.setYear("789");
>>
>> CarObject co = *new*CarObject();
>>
>> co.setCompany("Fiat");
>>
>> co.setName("Punto");
>>
>> co.setYear("789");
>>
>> VehicleObj vo = *new*VehicleObj();
>>
>> vo.setBusObj(bo);
>>
>> vo.setCar(car);
>>
>> vo.setCarObj(co);
>>
>> VehicleObj vo2 = *new*VehicleObj();
>>
>> vo2.setBusObj(bo);
>>
>> vo2.setCar(car);
>>
>> vo2.setCarObj(co);
>>
>> VehicleObj vo3 = *new*VehicleObj();
>>
>> vo3.setBusObj(bo);
>>
>> vo3.setCar(car);
>>
>> vo3.setCarObj(co);
>>
>> VehicleObjList list = *new*VehicleObjList();
>>
>> list.getVehicle().add(vo);
>>
>> list.getVehicle().add(vo2);
>>
>> list.getVehicle().add(vo3);
>>
>> ObjectFactory of = *new*ObjectFactory();
>>
>> *return*of.createVehicleList(list);
>>
>> }
>>
>> @POST
>>
>> @Path("putVehicles")
>>
>> @Produces(MediaType./TEXT_PLAIN/)
>>
>> @Consumes({MediaType./APPLICATION_JSON/, MediaType./APPLICATION_XML/})
>>
>> *public*String putVehicles(JAXBElement<VehicleObjList> element)
>>
>> {
>>
>> VehicleObjList list = element.getValue();
>>
>> List<VehicleObj> vehicle = list.getVehicle(); --ąTHIS RETURNS NULL
>>
>> *return*"true";
>>
>> }
>>
>> I have to use JAXBElement as the return types and parameters since the
>> JAXB Binding classes already exists and we cannot edit the schema to add
>> some @XmlRootElement's as this Binding classes are used in SOAP services
>> also.
>>
>> Please let me know if you have come across this issue and if so pls
>> suggest the solution you had to work around.
>>
>> Here is my ContextResolver implementation
>>
>> @Provider
>>
>> public final class JAXBContextResolver implements
>> ContextResolver<JAXBContext> {
>>
>> private final JAXBContext context;
>>
>> private final Set<Class> types;
>>
>> private final Class[] cTypes = { VehicleObjList.class, VehicleObj.class,
>> CarObject.class,
>>
>> CarType.class, BusObject.class };
>>
>> public JAXBContextResolver() throws Exception {
>>
>> this.types = new HashSet(Arrays.asList(cTypes));
>>
>> Map<String, String> ns2json = new HashMap<String, String>();
>>
>> ns2json.put("http://www.theserverlabs.com/namespaces/cars", "1");
>>
>> ns2json.put("http://www.theserverlabs.com/namespaces/bus", "2");
>>
>> this.context = new JSONJAXBContext(JSONConfiguration.mappedJettison()
>>
>> .xml2JsonNs(ns2json).build(), cTypes);
>>
>> }
>>
>> public JAXBContext getContext(Class<?> objectType) {
>>
>> return (types.contains(objectType)) ? context : null;
>>
>> }
>>
>> }
>>
>> Thanks& Regards
>>
>> Dhanush Gopinath
>>
>