3

This is not a duplicate of this question as the question here is specifically about representation of JSON strings serialized from Java in literal form in JavaScript (and it's more than double quotes one has to worry about).

I am creating in Java a serialized JSON object using Gson which I am subsequently unable to internalize from Javascript using JSON.parse. This occurs when I have escaped double quotes in my Java object. I find that baffling as Gson is supposed to take care of proper escaping and the JSON serialization format is language-agnostic so when I serialize from Java I should be able to deserialize from JavaScript without any headaches.

Minimal code below:

Java serialization

import java.util.*;
import java.lang.reflect.Type;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

class LOV {
    List<String> values;

    public LOV(List<String> values) {
        this.values = values;
    }
}

public class FooMain {

    private static final Gson gson = new GsonBuilder().serializeNulls().create();

    @SuppressWarnings("unchecked")
    public static <T> T fromJson(String json, Class<T> classOfT) {
        T target = (T) gson.fromJson(json, (Type) classOfT);
        return target;
    }

    public static void main(String args[]) {
        List<String> values = new ArrayList<>();
        values.add("\"foo\"");
        LOV lov = new LOV(values);
        String s = gson.toJson(lov);
        System.out.printf("Stringified JSON is: [%s]\n", s);
        LOV lov2 = fromJson(s, LOV.class);
    }
}

… the above code shows that serialization and deserialization is possible and works. I also wrote an equals method for the LOV class to establish that the re-internalized object (lov2) is equal to the originally serialized one (and it is, I am just skipping this code to keep this short).

The above code prints on the console:

Stringified JSON is: [{"values":["\"foo\""]}]

JavaScript internalization

Yet, when I am trying to internalize in JavaScript the string created by Java:

JSON.parse('{"values":["\"foo\""]}');

… I get:

Uncaught SyntaxError: Unexpected token f in JSON at position 13(…)

Resolution

In the end, based on the accepted answer and the commentary to it I automatically escaped a number of characters in the Java side but there were many cases to consider. So I had to do (in Java) all of the following:

s.replace("\\", "\\\\")
s.replace("\"", "\\\"")
s.replace("'", "\\'")

… and on the JavaScript side I also had to do:

JSON.parse('the string literal prepared by Java'.replace(/\t/g, "\\t"));

This is working but is getting complicated and I wasn't sure I had all the cases covered so in the end I just used StringEscapeUtils.escapeEcmaScript and it worked like a charm. Using escapeEcmaScript a simple JSON.parse('the string literal prepared by Java') was sufficient on the JavaScript side.

Marcus Junius Brutus
  • 26,087
  • 41
  • 189
  • 331
  • I think that's because you do quote the value but didn't escape the "\". `JSON.parse('[{"values":["\\"foo\\""]}]');` WFM –  Jul 18 '17 at 15:22
  • `JSON.parse('[{"values":["\\\"foo\\\""]}]');` you need to escape the backslash as well, so that is escapes the double quote. Another option is to potentially encode the double quote but yeah. – Sterling Archer Jul 18 '17 at 15:23

1 Answers1

2

You need to use double backslash for Javascript's JSON.parse. This should work:

JSON.parse('{"values":["\\"foo\\""]}');

This is because you also need to escape the backslash.

Marcus Junius Brutus
  • 26,087
  • 41
  • 189
  • 331
Chris
  • 2,435
  • 6
  • 26
  • 49
  • Changing the string literal by hand does work in this limited example, but I would need a function or regexp in Javascript to perform the replacement whenever it's needed. I've experimented with `.replace(/\\/g, "\\\\");` and various other forms but nothing seems to produce a string that JSON can parse in JavaScript. – Marcus Junius Brutus Jul 18 '17 at 16:32
  • https://stackoverflow.com/questions/16144090/replace-single-backslash-with-double-backslashes – Chris Jul 18 '17 at 16:35
  • I've obviously seen that, it's not working. This issue at hand is that the string given to Javascript (`'{"values":["\"foo\""]}'`) does not actually contain any backslashes to replace. The backslashes that appear are escape characters. It makes more sense to replace all double quotes in the string, but that also changes the stringified form of the property names resulting in failure. – Marcus Junius Brutus Jul 18 '17 at 16:43
  • 1
    Oh I see. And you can't add the extra escape characters on the Java end? – Chris Jul 18 '17 at 16:52
  • This is the next thing to try but since I was using the GSON library to JSON-stringify the object I was hoping that all necessary escapes were handled by the library somehow. Apparently sharing JSON strings among different languages runs into complications. – Marcus Junius Brutus Jul 18 '17 at 16:56
  • Yea I would add `.replace("\\", "\\\\");` to your Java side in the string if you can – Chris Jul 18 '17 at 17:09