Bug - Fixed Escaped backslashes in to_json()

Ezandora

Member
r17033

Example script:
Code:
void main()
{
	string input_string = "\\=\"";
	
	string [int] output_map;
	output_map[0] = input_string;
	output_map[1] = get_campground().to_json(); //to verify nested JSON
	string json = output_map.to_json();
	print_html(json);
}
Output:
Code:
{ "0" : "\=\"", "1" : "{ \"Certificate of Participation\" : 1, \"Dramatic™ range\" : 1, \"Queue Du Coq cocktailcrafting kit\" : 1, \"chef-in-the-box\" : 1, \"bartender-in-the-box\" : 1, \"pagoda plans\" : 1, \"Frobozz Real-Estate Company Instant House (TM)\" : 1, \"clockwork maid\" : 1, \"Discount Telescope Warehouse gift certificate\" : 1, \"ice harvest\" : 6, \"portable Mayo Clinic\" : 1, \"potted tea tree\" : 1, \"haunted doghouse\" : 1, \"Witchess Set\" : 1, \"Source terminal\" : 1 }" }
This is malformed JSON, as verified by a JSON validator. The initial backslash needs to be escaped:
Code:
{ "0" : "\\=\"", "1" : "{ \"Certificate of Participation\" : 1, \"Dramatic™ range\" : 1, \"Queue Du Coq cocktailcrafting kit\" : 1, \"chef-in-the-box\" : 1, \"bartender-in-the-box\" : 1, \"pagoda plans\" : 1, \"Frobozz Real-Estate Company Instant House (TM)\" : 1, \"clockwork maid\" : 1, \"Discount Telescope Warehouse gift certificate\" : 1, \"ice harvest\" : 6, \"portable Mayo Clinic\" : 1, \"potted tea tree\" : 1, \"haunted doghouse\" : 1, \"Witchess Set\" : 1, \"Source terminal\" : 1 }" }


I believe the fault to be in Value.java, in toJSON():
Code:
return "\"" + StringUtilities.globalStringReplace( this.toString(), "\"", "\\\"" ) + "\"";
It correctly escapes the quotation mark (as seen above) but not \. Maybe change to:
Code:
return "\"" + StringUtilities.globalStringReplace(StringUtilities.globalStringReplace( this.toString(), "\\", "\\\\"), "\"", "\\\"") + "\"";
 

heeheehee

Developer
Staff member
It looks simpler to just build a JSONObject and invoke toString once that's all done. It's probably more efficient, however, to invoke the methods of JSONStringer (although there seems to be an inherent max depth of 20 with JSONStringer that JSONObject doesn't have).

I wonder why my compiler can't seem to find JSONObject.valueToString(Object), when it can find JSONObject.valueToString(Object, int, int), even though the two methods have the same visibility.
 

Veracity

Developer
Staff member
I assume the max depth of 20 would be controllable by a constant in the source, or something.
We control our copy of the source.
 

heeheehee

Developer
Staff member
On top of this: JSONStringer is only relevant if we're stringifying an object or array, as it can't convert JSON primitives (notably, Strings, which need to be quoted anyways). r17035 implements this via the first approach.
 

heeheehee

Developer
Staff member
I assume the max depth of 20 would be controllable by a constant in the source, or something.
We control our copy of the source.

And yes, this is a correct assumption and a valid point. Another reason why I ended up implementing this the way I did was that it simply looked syntactically cleaner.
 

heeheehee

Developer
Staff member
Hm. This doesn't quite handle nested structures or constants correctly. Looking into it.

edit: wait, no, that's just Ezandora's test being strangely implemented. Move along, nothing to see here.
 
Last edited:

heeheehee

Developer
Staff member
One thing I wonder, though. Since plural typed constants are internally implemented as ArrayLists, does it make sense to also stringify those as JSON arrays?
 

Veracity

Developer
Staff member
Seems reasonable - especially if we decide we want a from_json() function which would do its best to be the inverse of to_json().
 

heeheehee

Developer
Staff member
from_json() seems tricky, since JSON objects are polymorphic (in the sense that they can store multiple types as values). I don't see a natural implementation -- the closest we can get is with records, which just doesn't work here, since the record definition isn't fixed.
 

heeheehee

Developer
Staff member
Hm, apparently I've been mistaken that PluralValues are ArrayLists under the hood -- while the constructor does take an ArrayList of values, it immediately converts that to an array.

Regardless, the implementation is identical to ArrayValue's. r17036 adds this; briefly tested.
 

Veracity

Developer
Staff member
Well, my assumption would be that it'd only be possible if you'd created the string with to_json(). You are correct that JSON objects with multiple data types would have to go into a record, and since ASH doesn't let you define record types at runtime, it'd have to go into an already defined record type - and determining which one to use could be tricky. Well, mabe not; recursion is your friend.

In any case, we haven't had a swell of demand for from_json(), yet. I'd wait for somebody to provide a reasonable use case before I'd move on it.
 

heeheehee

Developer
Staff member
Perhaps the closest thing we have in ASH is call, wherein you need to explicitly state the return type of the invoked function; if the interpreter detects a mismatch, it throws a runtime error.

And agreed, I don't see an immediate need, as ASH already has serialization / deserialization in the form of map_to_file and file_to_map.
 
Top