Json Converter

View: New views
3 Messages — Rating Filter:   Alert me  

Json Converter

by Steve Skrla :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Ok, I have tried running this down in the group but I haven't really found anything that speaks to it directly, so I apologize if this is a repost.

There are numerous situations where I want to store Json data 'on' a user and retrieve that information unmolested in the future (mostly for interface component states which can take any form). As far as I can tell, there are no converters provided by default that allow you to have a field, say User.settings of type JsonValue, and have it handled in the described manner. So I've started writing one which works, mostly, but I am having issues with line 89 in the attached file.  The internals of the JsonUtil.parse are supposed to take the value and return a JsonNull, JsonString, or JsonNumber depending on the provided input. Only strings that get to this line are not encapsolated by quotation marks which trips up the parser and makes type detection a little more difficult.  Ideally, I would like to drop the parsing all together and use the type information that is ON the InboundVariable, but it is not exposed.

So, my questions are:
  1. Why is the type information of an InboundVariable not exposed.
  2. Is there is there a better (potentially obvious) way to do this?

Thanks,

--Steve Skrla

[JsonValueConverter.java]

package com.qualys.common.dwr;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Map.Entry;

import org.directwebremoting.ConversionException;
import org.directwebremoting.extend.ArrayOutboundVariable;
import org.directwebremoting.extend.ConvertUtil;
import org.directwebremoting.extend.Converter;
import org.directwebremoting.extend.ConverterManager;
import org.directwebremoting.extend.InboundContext;
import org.directwebremoting.extend.InboundVariable;
import org.directwebremoting.extend.NonNestedOutboundVariable;
import org.directwebremoting.extend.ObjectOutboundVariable;
import org.directwebremoting.extend.OutboundContext;
import org.directwebremoting.extend.OutboundVariable;
import org.directwebremoting.extend.ProtocolConstants;
import org.directwebremoting.json.types.JsonArray;
import org.directwebremoting.json.types.JsonObject;
import org.directwebremoting.json.types.JsonValue;

import com.qualys.common.util.JsonUtil;


/**
 * Converts to and from <tt>JsonValue</tt>s.
 *
 * @author Steve Skrla
 */
public class JsonValueConverter implements Converter {
        private ConverterManager manager;
       
        @Override
        public Object convertInbound(Class<?> paramType, InboundVariable data) {
                return convert(data, data.getContext());
        }
       
        private JsonValue convert(InboundVariable data, InboundContext inctx) {
                String value = data.getValue();
               
                if(value.startsWith(ProtocolConstants.INBOUND_MAP_START)) {
                        value = value.substring(
                                value.indexOf(ProtocolConstants.INBOUND_MAP_START) + 1,
                                value.lastIndexOf(ProtocolConstants.INBOUND_MAP_END));
                       
                        JsonObject ret = new JsonObject();
                       
                        StringTokenizer tokens = new StringTokenizer(value, ProtocolConstants.INBOUND_MAP_SEPARATOR);
                        while(tokens.hasMoreTokens()) {
                                String token = tokens.nextToken().trim();
                               
                                if(token.length() == 0) {
                                        continue;
                                }
                               
                                int splitIndx = token.indexOf(ProtocolConstants.INBOUND_MAP_ENTRY);
                                if(splitIndx == 1) {
                                        throw new ConversionException(JsonObject.class);
                                }
                               
                                String    key = token.substring(0, splitIndx).trim();
                                JsonValue val = dereference(token.substring(splitIndx + 1), data, inctx);
                                ret.put(key, val);
                        }
                       
                        return ret;
                       
                } else if(value.startsWith(ProtocolConstants.INBOUND_ARRAY_START)) {
                        value = value.substring(
                                value.indexOf(ProtocolConstants.INBOUND_ARRAY_START) + 1,
                                value.lastIndexOf(ProtocolConstants.INBOUND_ARRAY_END));
                       
                        JsonArray ret = new JsonArray();
                        StringTokenizer tokens = new StringTokenizer(value, ProtocolConstants.INBOUND_ARRAY_SEPARATOR);
                        while(tokens.hasMoreTokens()) {
                                String token = tokens.nextToken().trim();
                                if(token.length() > 0)
                                        ret.add(dereference(token, data, inctx));
                        }
                       
                        return ret;
                       
                } else {
                       
                        return JsonUtil.parse(value);
                }
        }
       
        private JsonValue dereference(String value, InboundVariable data, InboundContext inctx) {
                String[] split = ConvertUtil.splitInbound(value);
                String splitValue = split[ConvertUtil.INBOUND_INDEX_VALUE];
                String splitType = split[ConvertUtil.INBOUND_INDEX_TYPE];
         
        InboundVariable nested = new InboundVariable(data.getContext(), null, splitType, splitValue);
        nested.dereference();
        return convert(nested, inctx);
        }

        @Override
        public OutboundVariable convertOutbound(Object data, OutboundContext outctx) {
                if(data instanceof JsonObject) {
                        return convertObject((JsonObject) data, outctx);
                } else if(data instanceof JsonArray) {
                        return convertArray((JsonArray) data, outctx);
                } else {
                        return convertPrimative((JsonValue) data, outctx);
                }
        }

        @Override
        public void setConverterManager(ConverterManager converterManager) {
                this.manager = converterManager;
        }
       
        protected OutboundVariable convertArray(JsonArray array, OutboundContext ctx) {
                ArrayOutboundVariable ov = new ArrayOutboundVariable(ctx);
               
                List<OutboundVariable> items = new ArrayList<OutboundVariable>();
                ctx.put(array, ov);
                for(JsonValue value: array) {
                        items.add(manager.convertOutbound(value, ctx));
                }
                ov.setChildren(items);
               
                return ov;
        }
       
        protected OutboundVariable convertObject(JsonObject object, OutboundContext ctx) {
                ObjectOutboundVariable ov = new ObjectOutboundVariable(ctx);
               
                Map<String, OutboundVariable> items = new HashMap<String, OutboundVariable>();
                ctx.put(object, ov);
                for(Entry<String, JsonValue> entry: object.entrySet()) {
                        items.put(
                                entry.getKey(),
                                manager.convertOutbound(entry.getValue(), ctx));
                }
                ov.setChildren(items);
               
                return ov;
        }
       
        protected OutboundVariable convertPrimative(JsonValue object, OutboundContext ctx) {
                return new NonNestedOutboundVariable(object.toExternalRepresentation());
        }
}


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@...
For additional commands, e-mail: users-help@...

Re: Json Converter

by davidmarginian :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Correct me if I am wrong, you just want to store a representation of the
object as a JSON string?  If this is the case, I think you are going
through too much trouble.  If you are working with the latest code from
trunk take a look at dwr/ui/demo/web/json/jquery/people/edit.js.  It
illustrates an example of jquery making a DWR request and encoding a
JSON object (using the jquery, jquery.json plugin):

$.post("../../../dwr/jsonp/People/setPerson?param0=" +
encodeURIComponent($.toJSON(person)), { },

You can do the same sort of thing and just pass your remoted method a
JSON String.  If it is a String DWR won't muck with it.

Steve Skrla wrote:

> Ok, I have tried running this down in the group but I haven't really
> found anything that speaks to it directly, so I apologize if this is a
> repost.
>
> There are numerous situations where I want to store Json data 'on' a
> user and retrieve that information unmolested in the future (mostly
> for interface component states which can take any form). As far as I
> can tell, there are no converters provided by default that allow you
> to have a field, say User.settings of type JsonValue, and have it
> handled in the described manner. So I've started writing one which
> works, mostly, but I am having issues with line 89 in the attached
> file.  The internals of the JsonUtil.parse are supposed to take the
> value and return a JsonNull, JsonString, or JsonNumber depending on
> the provided input. Only strings that get to this line are not
> encapsolated by quotation marks which trips up the parser and makes
> type detection a little more difficult.  Ideally, I would like to drop
> the parsing all together and use the type information that is ON the
> InboundVariable, but it is not exposed.
>
> So, my questions are:
>   1. Why is the type information of an InboundVariable not exposed.
>   2. Is there is there a better (potentially obvious) way to do this?
>
> Thanks,
>
> --Steve Skrla
> ------------------------------------------------------------------------
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@...
> For additional commands, e-mail: users-help@...
>
>
> __________ Information from ESET NOD32 Antivirus, version of virus signature database 4494 (20091009) __________
>
> The message was checked by ESET NOD32 Antivirus.
>
> http://www.eset.com
>



__________ Information from ESET NOD32 Antivirus, version of virus signature database 4494 (20091009) __________

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@...
For additional commands, e-mail: users-help@...


Re: Json Converter

by Steve Skrla :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Sorry, I am not familiar with mailing list mechanics (apparently I am not automatically subscribed to responses to my original message?). Hopefully this gets where it is supposed to go ^.^ In case it doesn't match up, this is in response to http://markmail.org/message/yeshifqpfdxq7xdc

David: Thanks for the response. You are correct in your understanding / solution, and I did say that I did not want the data to be modified. However, I would like to allow for the possibility of modification and I feel that storing input from a post directly in the database is ... dangerous. I guess I could run the provided string through a quick JSON parse to see if it validates before persisting certain objects, but I would feel much safer it it was implicit.

A side note: I am using a reflection hack to get at the type information. I can open a improvment ticket to ask for a getter if there is not some design decision keeping this information hidden.