how can one strip quotes from the resulting JSON strings?

5,706 views
Skip to first unread message

Victor

unread,
Dec 14, 2010, 6:05:21 PM12/14/10
to google-gson
I am looking for a way to generate JSON output where some field values
would not have double quotes around them, below is what I need (pay
attention to Ext.util.Format.usMoney) ) :

[
{"header": "Price", "width": 20, "sortable": "true", "renderer":
Ext.util.Format.usMoney, "dataIndex": "price"}
]

Instead I get:

[
{"header": "Price", "width": 20, "sortable": "true", "renderer":
"Ext.util.Format.usMoney", "dataIndex": "price"}
]

I tried everything, including creating my own JsonSerializer, but I
cant find a way to dump a string w/o double quotes sneaking in as
result in JSON output... Please help :(

Angel Aguilera

unread,
Dec 15, 2010, 2:30:29 AM12/15/10
to google-gson
I'm sorry, but I think what you are trying to generate is not a valid
JSON string.
Conforming to JSON standard, object attributes must be in the form

attribute : value

where (quoting from http://www.json.org):

"A value can be a string in double quotes, or a number, or true or
false or null, or an object or an array. These structures can be
nested."

I understand the quotes are mandatory except for numbers, objects
(something between "{" and "}") and arrays (something between "[" and
"]").

Please somebody correct me if I'm wrong, but I think you won't be able
to generate
your desired output with Gson, so you probably should strip the quotes
from the
Gson output with some custom code.

Victor

unread,
Dec 15, 2010, 9:31:56 AM12/15/10
to google-gson
From the definition it appears your interpretation is correct, but how
would one make a call to a function (as that's exactly what it is)?
Also, if there is no built in way to do it can somebody suggest an
elegant enough workaround? (not too abstract) I would really prefer
doing it with GSON - up to modifying the source locally. I really
appreciate your help. Thanks in advance.

On Dec 15, 2:30 am, Angel Aguilera <angel.aguil...@gmail.com> wrote:
> On Dec 15, 12:05 am, Victor <victorley...@gmail.com> wrote:
>
>
>
> > I am looking for a way to generate JSON output where some field values
> > would not have double quotes around them, below is what I need (pay
> > attention to Ext.util.Format.usMoney) ) :
>
> > [
> >     {"header": "Price", "width": 20, "sortable": "true", "renderer":
> > Ext.util.Format.usMoney, "dataIndex": "price"}
> >  ]
>
> > Instead I get:
>
> > [
> >     {"header": "Price", "width": 20, "sortable": "true", "renderer":
> > "Ext.util.Format.usMoney", "dataIndex": "price"}
> >  ]
>
> > I tried everything, including creating my own JsonSerializer, but I
> > cant find a way to dump a string w/o double quotes sneaking in as
> > result in JSON output... Please help :(
>
> I'm sorry, but I think what you are trying to generate is not a valid
> JSON string.
> Conforming to JSON standard, object attributes must be in the form
>
> attribute : value
>
> where (quoting fromhttp://www.json.org):

Victor

unread,
Dec 15, 2010, 11:20:46 AM12/15/10
to google-gson
I found a client-side workaround (hack), basically I iterated through
the json result on the client-side grabbing my "renderer" field and
setting it with eval:

var x;
for(x in JSONPayload){
if (JSONPayload[x].renderer != undefined){
JSONPayload[x].renderer =
eval(JSONPayload[x].renderer);
}
}
Not cool to not be able to handle this on the server-side... Perhaps
JSON specification needs to be amended.....

Pawel Veselov

unread,
Dec 15, 2010, 2:03:40 PM12/15/10
to googl...@googlegroups.com

You may want to try this:

1. in your custom seralizer, where you need to return an instance of JsonElement, return your own JsonElement implementation. (it would be cool if you could return your own instance of JsonPrimitive, but the method that writes out strings is final).

2. Your JsonElement implementation will have an overridden toString(Appendable, Escaper) method. In this method, return the string in the way you want, which will be no quotes, and whatever else you wish to do with it.

Unfortunately, GSON puts two road blocks to this approach. First, as I said, the toString(Appendable,Escaper) is final in JsonPrimitive, so you can't extend it (which would be simpler, and guarantee that things won't break if getAsXXX() methods are called from inside GSON framework, and these methods are likely to fail on your extension of JsonElement).

Second, is that the Escaper class is package private. So your extended class must be in the same package as the Escaper, which is com.google.gson.

Note that I was looking into version 1.5, things may be different in 1.6.

Regarding the JSON specification. Look, what you are trying to do is, generally, wrong, when it comes to the perspective of JSON as a language. The language has its rules which you are trying to bend. It's like asking XML producer to produce tags that have '>' literal inside their name. I guess your goal is to make the client side JS that reads JSON automatically execute something upon receiving the data. JSON was defined for data transfer language only, it was not defined for executing code. Allowing generic JSON to execute things around would make it a programming language, which it is not, and will open doors for letting people sneak in arbitrarily executed code sequences in data stream, which is generally just a big security hole.

Victor Leyner

unread,
Dec 15, 2010, 3:06:51 PM12/15/10
to googl...@googlegroups.com
Pasha I definitely have tried what you're describing already - I actually got the source code and hacked it for a whiiile, but the part responsible for the quotes is much deeper embedded some place else (had no patience to trace that far). I sincerely appreciate you taking time and effort to help, thank you.

I agree with you on the specific need which JSON specification was satisfying, that being transportation of data. Having said that, my need is to configure definitions of ExtJs components via JSON (not merely feed it data for showing) which may need helper functions inferred for things like string formatting etc. If one was to try to define the general term "data transportation", where in it does it say you are limited to specific data? (I know JSON apparently does :) )

As far as security, what's there to prevent me from intercepting a stream and inserting java script by the same token. So I am not sure the limitation really makes it all that much more secure, but I understand what they were going for initially.

--
You received this message because you are subscribed to the Google Groups "google-gson" group.
To post to this group, send email to googl...@googlegroups.com.
To unsubscribe from this group, send email to google-gson...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-gson?hl=en.

Pawel Veselov

unread,
Dec 15, 2010, 3:16:52 PM12/15/10
to googl...@googlegroups.com
Hi Victor,

so you are saying that serialization process does not call:

  @Override
  protected void toString(Appendable sb, Escaper escaper) throws IOException {
    if (isString()) {
      sb.append('"');
      sb.append(escaper.escapeJsonString(value.toString()));
      sb.append('"');
    } else {
      sb.append(value.toString());
    }
  }


which puts the quotes out?

(I actually misspoke before, the method is not final, but the JsonPrimitive class is final).
--
With best of best regards
Pawel S. Veselov

Victor

unread,
Dec 15, 2010, 3:20:34 PM12/15/10
to google-gson
Below is a more generic solution I just wrote, for anyone to use as
they wish, if they wish. Be careful with large/complex objects as
recursion is used:

/**
* This function will iterate through an object and turn values of
it's fields
* that are strings into function call (or whatever else) using
eval(). The purpose at the time
* was to workoaround JSON limitation of not allowing function call
per its spec.
* i.e. [{"header": "Price", "width": 20, "sortable": "true",
"renderer": "Ext.util.Format.usMoney", "dataIndex": "price"}]
* the Ext.util.Format.usMoney is a function, but JSON wraps it into
quotes.
* @param {Object} propertyName The name of the property/field whose
values we
* are about to eval().
* @param {String} objRef The object to be searched
*/
function functionMaker(propertyName, objRef){
var x;
//if we are dealing with an array, recursively iterate
if(objRef instanceof Array){
for(i=0; i<objRef.length; i++){
functionMaker(propertyName, objRef[i])
}
}
for(x in objRef){
if((x != undefined) && (x == propertyName)){
objRef[x] = eval(objRef[x]); //fixed ya!
} else if(objRef[x] instanceof Array){ //if we are dealing
with an array, recursively iterate
for(i=0; i<objRef[x].length; i++){
functionMaker(propertyName, objRef[x][i])
}
}
}
}

On Dec 14, 6:05 pm, Victor <victorley...@gmail.com> wrote:

Victor Leyner

unread,
Dec 15, 2010, 3:23:09 PM12/15/10
to googl...@googlegroups.com
Yeah that there is actually not it - that was the first thing that caught my eye, I rigged it right away - it's something else, or perhaps just redundant.

George Francis

unread,
Jan 29, 2014, 9:22:36 PM1/29/14
to googl...@googlegroups.com
This is a great idea Victor, however the functionMaker gets into an infinite loop on nested columns such as this:

<pre>

columns:[{

text:"Name",

dataIndex:"name"

},{

text:"Data",

columns:[{

text:"Cost",

dataIndex:"datacost",

renderer:"gbpFormat"

}]},

{

text:"Roaming",

columns:[{

text:"Cost",

dataIndex:"roamcost",

renderer:"gbpFormat"

}]}

]

</pre>

Reply all
Reply to author
Forward
0 new messages