users@jersey.java.net

Re: [Jersey] can i use jersey's json Unmarshaller?

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Mon, 15 Dec 2008 14:10:30 +0100

Hi,

Jakub is currently refactoring the JSON/JAXB support to make it easier
to reuse in different contexts that you require but as of now i would
not recommend it. So the way to support this today is to obtain the
message body reader for the JAXB type.

In your own reader you can inject an instance of
javax.ws.rs.ext.Providers:

   @Context Providers ps;

Then you can call:

   MessageBodyReader<E> mbr = ps.getMessageBodyReader(...)

the media type parameter must be "application/json". You can reuse the
same mediaType instance passed to your message body writer.

Then you can use "mbr" to read the JSON to a JAXB instance. But just
one annoying thing: the JSONObject needs to be serialized back to
bytes that are encapsulated in a ByteArrayInputStrea, which is passed
to the mbr.readFrom method.

Hope this helps,
Paul.

[1] https://jsr311.dev.java.net/nonav/javadoc/javax/ws/rs/ext/Providers.html

On Dec 11, 2008, at 4:30 PM, beanor wrote:

>
> Hi Paul:
>
> First, Thanks for telling me MapReader is a singleton class, Yes, I
> have a
> mistake for creating a new instanse of HashMap on Class' Filed.
>
> Yes , you are correct,I want to convert JSON document that consists of
> methods to be applied to an array of JSON objects, Each JSON object
> unmarshall to JAXB.
>
> I see, We can use JSONObject or JSONArray instead of HashMap<String,
> List<E>>() ,But,As this case:
>
> 1. We have a lot of time to Convert JSONOjbet and JSONArray to my
> persistent Model, We hope uniform Model crossing client and server.
> Resource
> class's responsibility is not serializer.
> 2. We hope that the Resource class is simple and clear.
> 3. We also think that supporting convert JSONObject to JAXB in
> MessageBodyReader or convert JAXB to JSONObject is very useful for
> Jersey'
> user. it has improve Jersey framework's expansibility and agility.
>
> My viewpoint is not always correct, Please point my error viewpoint .
>
> Regards!
>
> Jack.
>
>
>
>
> Paul Sandoz wrote:
>> ,
>> Hi,
>>
>> It looks like your MessageBodyReader should work OK with one
>> modification. In the readFrom method you need to create a new
>> instance
>> of new HashMap<String, List<E>>() and not use the one on the field.
>> The MapReader is a singleton class.
>>
>> Jersey supports Jettison's JSONObject and JSONArray directly for
>> resource methods, but i do not think this helps you.
>>
>> If i understand correctly you have a JSON document that consists of
>> methods to be applied to an array of JSON objects. Each JSON objects
>> need to be unmarshaled to a Java bean or in your case you want to
>> unmarshal them to JAXB objects? is that correct?
>>
>> If so i think there are ways you can do this. But i would like to
>> know
>> if i have understood your use-case correctly before proposing a
>> solution (which i would involve reusing the JAXB message body readers
>> in your own MapReader.
>>
>> Paul.
>>
>>
>> On Dec 11, 2008, at 2:35 AM, beanor wrote:
>>
>>>
>>> paul:
>>>
>>> I am very Sorry for sending a bad code to you, Because that code
>>> include
>>> some chinese character.I had read the entity-provider-1.0.1-
>>> project.zip when
>>> sending the thread before, and i had wrote the code following the
>>> entity-provider example.
>>>
>>> Following the right code:
>>>
>>> ====================================
>>> package com.jersey.sample.provider;
>>>
>>> import java.io.IOException;
>>> import java.io.InputStream;
>>> import java.io.InputStreamReader;
>>> import java.io.Reader;
>>> import java.lang.annotation.Annotation;
>>> import java.lang.reflect.Type;
>>> import java.util.ArrayList;
>>> import java.util.HashMap;
>>> import java.util.List;
>>> import java.util.Map;
>>>
>>> import javax.ws.rs.Consumes;
>>> import javax.ws.rs.WebApplicationException;
>>> import javax.ws.rs.core.MediaType;
>>> import javax.ws.rs.core.MultivaluedMap;
>>> import javax.ws.rs.ext.MessageBodyReader;
>>> import javax.ws.rs.ext.Provider;
>>>
>>> import net.sf.json.JSONArray;
>>> import net.sf.json.JSONObject;
>>> import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
>>>
>>> import com.jersey.sample.Constant;
>>>
>>> /**
>>> *
>>> * @author Jack Dou
>>> * @since Dec 10, 2008
>>> */
>>> @Consumes("application/json")
>>> @Provider
>>> public class MapReader<E> implements MessageBodyReader<Map<String,
>>> List<E>>>
>>> {
>>> private static String[] methods = { "add", "delete", "update" };
>>> private Map<String, List<E>> returnMap = new HashMap<String,
>>> List<E>>();
>>>
>>> public boolean isReadable(Class<?> type, Type genericType,
>>> Annotation[] annotations, MediaType mediaType) {
>>> return type.isAssignableFrom(Map.class);
>>> }
>>>
>>> @SuppressWarnings("unchecked")
>>> public Map<String, List<E>> readFrom(Class<Map<String, List<E>>>
>>> type,
>>> Type genericType, Annotation[] annotations, MediaType
>>> mediaType,
>>> MultivaluedMap<String, String> httpHeaders, InputStream
>>> entityStream)
>>> throws IOException, WebApplicationException {
>>> String formData = readAsString(entityStream);
>>> JSONObject fromObj = JSONObject.fromObject(formData);
>>> Class<E> cls = getActualClass(genericType);
>>> for (String method : methods) {
>>> boolean isHasTheMethod = fromObj.containsKey(method);
>>> if (isHasTheMethod) {
>>> JSONArray arr = fromObj.getJSONArray(method);
>>> List<E> list = new ArrayList<E>();
>>> for (int i=0,size = arr.size(); i<size; i++) {
>>> JSONObject tempObj = (JSONObject)arr.get(i);
>>> JSONObject.toBean(tempObj, cls);
>>> list.add((E)JSONObject.toBean(tempObj, cls));
>>> }
>>> returnMap.put(method, list);
>>> }
>>> }
>>> return returnMap;
>>> }
>>>
>>> @SuppressWarnings("unchecked")
>>> public Class<E> getActualClass(Type genericType) {
>>> ParameterizedTypeImpl pti = (ParameterizedTypeImpl)
>>> genericType;
>>> Type[] types = pti.getActualTypeArguments();
>>> ParameterizedTypeImpl type = (ParameterizedTypeImpl) types[1];
>>> Type[] types2 = type.getActualTypeArguments();
>>> Class<E> type2 = (Class<E>) types2[0];
>>> return type2;
>>> }
>>>
>>> public final String readAsString(InputStream in) throws
>>> IOException {
>>> Reader reader = new InputStreamReader(in,Constant.CHARSET);
>>> StringBuilder sb = new StringBuilder();
>>> char[] c = new char[1024];
>>> int l;
>>> while ((l = reader.read(c)) != -1) {
>>> sb.append(c, 0, l);
>>> }
>>> return sb.toString();
>>> }
>>> }
>>> =====================================
>>>
>>>
>>> Paul Sandoz wrote:
>>>>
>>>> Why are you passing methods in the request? The methods "add",
>>>> "delete", "update" can correspond to POST, DELETE and PUT methods
>>>> in
>>>> HTTP.
>>>>
>>>
>>> We want deal batch,So we sent a HTTP POST method from browser
>>> client, This
>>> idea is from google restful api:
>>> http://code.google.com/apis/calendar/developers_guide_protocol.html#batch
>>>
>>> I don't my way is right or not , Do you point it ?
>>>
>>> whether or not , I want implement convert a json string to java Map
>>> Object,
>>> Can you give me a example if you can, your entity-provider example
>>> is
>>> consucesing a application/x-www-form-urlencoded MidiaType, not is
>>> application/json.
>>>
>>> Ps: Is Converting json string to Java Set Object implemented for
>>> jersey1.0.1
>>> default?
>>>
>>> I am very thanks for your so soon replay. expacting your replay
>>> again.
>>>
>>> Best Regards!
>>>
>>> yours Jack from beijing.
>>>
>>>
>>>
>>> Paul Sandoz wrote:
>>>>
>>>> Hi,
>>>>
>>>> The source code you sent looks like it is corrupted, namely the
>>>> readFrom method has the following:
>>>>
>>>> for (int i=0,size = arr.size(); i getActualClass(Type
>>>> genericType) {
>>>> ParameterizedTypeImpl pti = (ParameterizedTypeImpl)
>>>> genericType;
>>>> Type[] types = pti.getActualTypeArguments();
>>>> ParameterizedTypeImpl type = (ParameterizedTypeImpl)
>>>> types[1];
>>>> Type[] types2 = type.getActualTypeArguments();
>>>> Class type2 = (Class) types2[0];
>>>> return type2;
>>>>
>>>> So i cannot evaluate the code properly.
>>>>
>>>> There is no existing functionality to return a Map instance for a
>>>> JSON
>>>> entity. The closest supported Java type is JSONObject from the
>>>> jettison library.
>>>>
>>>> Why are you passing methods in the request? The methods "add",
>>>> "delete", "update" can correspond to POST, DELETE and PUT methods
>>>> in
>>>> HTTP.
>>>>
>>>> For an example of implementing providers you can look at the
>>>> following
>>>> sample:
>>>>
>>>>
>>>> http://download.java.net/maven/2/com/sun/jersey/samples/entity-provider/1.0.1/entity-provider-1.0.1-project.zip
>>>>
>>>> Paul.
>>>> On Dec 10, 2008, at 11:39 AM, beanor wrote:
>>>>
>>>>> hi paul: I want Unmarshall a json string to Map param of Resource'
>>>>> method,now , I do it as follow:
>>>>> package com.jersey.sample.provider;
>>>>>
>>>>> import java.io.IOException;
>>>>> import java.io.InputStream;
>>>>> import java.io.InputStreamReader;
>>>>> import java.io.Reader;
>>>>> import java.lang.annotation.Annotation;
>>>>> import java.lang.reflect.Type;
>>>>> import java.util.ArrayList;
>>>>> import java.util.HashMap;
>>>>> import java.util.List;
>>>>> import java.util.Map;
>>>>>
>>>>> import javax.ws.rs.Consumes;
>>>>> import javax.ws.rs.WebApplicationException;
>>>>> import javax.ws.rs.core.MediaType;
>>>>> import javax.ws.rs.core.MultivaluedMap;
>>>>> import javax.ws.rs.ext.MessageBodyReader;
>>>>> import javax.ws.rs.ext.Provider;
>>>>>
>>>>> import net.sf.json.JSONArray;
>>>>> import net.sf.json.JSONObject;
>>>>> import
>>>>> sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
>>>>>
>>>>> import com.jersey.sample.Constant;
>>>>>
>>>>> /**
>>>>> *
>>>>> * @author Jack Dou
>>>>> * @since Dec 10, 2008
>>>>> */
>>>>> @Consumes("application/json")
>>>>> @Provider
>>>>> public class MapReader implements MessageBodyReader>> {
>>>>> private static String[] methods = { "add", "delete", "update" };
>>>>> private Map> returnMap = new HashMap>();
>>>>>
>>>>> public boolean isReadable(Class type, Type genericType,
>>>>> Annotation[] annotations, MediaType mediaType) {
>>>>> return type.isAssignableFrom(Map.class);
>>>>> }
>>>>>
>>>>> @SuppressWarnings("unchecked")
>>>>> public Map> readFrom(Class>> type,
>>>>> Type genericType, Annotation[] annotations, MediaType
>>>>> mediaType,
>>>>> MultivaluedMap httpHeaders, InputStream entityStream)
>>>>> throws IOException, WebApplicationException {
>>>>> String formData = readAsString(entityStream);
>>>>> JSONObject fromObj = JSONObject.fromObject(formData);
>>>>> Class cls = getActualClass(genericType);
>>>>> for (String method : methods) {
>>>>> boolean isHasTheMethod = fromObj.containsKey(method);
>>>>> if (isHasTheMethod) {
>>>>> JSONArray arr = fromObj.getJSONArray(method);
>>>>> List list = new ArrayList();
>>>>> for (int i=0,size = arr.size(); i
>>>>> getActualClass(Type genericType) {
>>>>> ParameterizedTypeImpl pti = (ParameterizedTypeImpl)
>>>>> genericType;
>>>>> Type[] types = pti.getActualTypeArguments();
>>>>> ParameterizedTypeImpl type = (ParameterizedTypeImpl)
>>>>> types[1];
>>>>> Type[] types2 = type.getActualTypeArguments();
>>>>> Class type2 = (Class) types2[0];
>>>>> return type2;
>>>>> }
>>>>>
>>>>> /**
>>>>> * 转化读取输入流中的数据为字符串型
>>>>> *
>>>>> * @param in 输入流
>>>>> * @return 输入流转化后的字符串
>>>>> * @throws IOException 输入流转化字符串失败,则报IO
>>>>> 异常
>>>>> */
>>>>> public final String readAsString(InputStream in) throws
>>>>> IOException {
>>>>> Reader reader = new InputStreamReader(in,Constant.CHARSET);
>>>>> StringBuilder sb = new StringBuilder();
>>>>> char[] c = new char[1024];
>>>>> int l;
>>>>> while ((l = reader.read(c)) != -1) {
>>>>> sb.append(c, 0, l);
>>>>> }
>>>>> return sb.toString();
>>>>> }
>>>>> }
>>>>> But I use json-lib.jar ,not jettison.jar, Can you gei me a demo
>>>>> for
>>>>> manual Unmarshall a json string to Map param using jersey default
>>>>> way? My English is poor,Sorry,Do you understand my meaning?
>>>>> View this message in context: can i use jersey's json
>>>>> Unmarshaller?
>>>>> Sent from the Jersey mailing list archive at Nabble.com.
>>>>
>>>>
>>>>
>>>
>>> --
>>> View this message in context:
>>> http://n2.nabble.com/can-i-use-jersey%27s-json-Unmarshaller--tp1638158p1641498.html
>>> Sent from the Jersey mailing list archive at Nabble.com.
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>
>>
>>
>
> --
> View this message in context: http://n2.nabble.com/can-i-use-jersey%27s-json-Unmarshaller--tp1638158p1643584.html
> Sent from the Jersey mailing list archive at Nabble.com.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>