users@jersey.java.net

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

From: Dhanush Gopinath <dhanush.gopinath_at_altair.com>
Date: Mon, 22 Nov 2010 10:49:43 +0530

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
>