10

I'm using Google's com.google.api.client.json.GenericJson and com.fasterxml.jackson.core.JsonGenerator. I would like to serialize JSON object and escape quotes and backslashes so that I can pass that string in Bash. And afterwards deserialize that string.

GenericJson.toString produces simple JSON, but \n etc. are not escaped:

{commands=ls -laF\ndu -h, id=0, timeout=0}

is there a simple way how to get something like this:

"{commands=\"ls -laF\\ndu -h\", id=0, timeout=0}"

I don't want to reinvent the wheel, so I'd like to use Jackson or an existing API, if possible.

Barett
  • 5,226
  • 6
  • 46
  • 53
Tombart
  • 26,066
  • 13
  • 112
  • 120
  • You might be looking for [this](http://stackoverflow.com/a/16652683/1066946) – Philipp Gayret Feb 05 '14 at 12:12
  • I was trying to avoid writing it from scratch, there's also Apache Commons method to escape JavaScript: http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringEscapeUtils.html#escapeJavaScript(java.lang.String) – Tombart Feb 05 '14 at 12:22
  • Stick the serialized JSON into an array and run it through the serializer a second time, then strip off the `[]` characters. – Hot Licks Feb 05 '14 at 13:33

2 Answers2

36

No additional dependencies needed: You're looking for JsonStringEncoder#quoteAsString(String).

Click for JsonStringEncoder javadoc

Example:

import com.fasterxml.jackson.core.io.JsonStringEncoder;

JsonStringEncoder e = JsonStringEncoder.getInstance();
String commands = "ls -laF\\ndu -h";
String encCommands = new String(e.quoteAsString(commands));
String o = "{commands: \"" + encCommands + "\", id: 0, timeout: 0}"

Ref: http://fasterxml.github.io/jackson-core/javadoc/2.1.0/com/fasterxml/jackson/core/io/JsonStringEncoder.html

Barett
  • 5,226
  • 6
  • 46
  • 53
4

Using Gson for serialization proved to be quite easy and bulletproof. Afterwards Apache's commons-lang3 = 3.1 escapeEcmaScript is used. In 3.2 there's also escapeJson method.

import com.google.api.client.json.GenericJson;
import com.google.api.client.util.Key;
import com.google.gson.Gson;
import org.apache.commons.lang3.StringEscapeUtils;

public class MyJson extends GenericJson {

    @Key("commands")
    public String commands;

    public String serialize() throws IOException {
      Gson gson = new Gson();
      String g = gson.toJson(this);
      return StringEscapeUtils.escapeEcmaScript(g);
    }
}

This produces escaped JSON:

{\"commands\":\"ls -laF\\ndu -h\"}

Deserialization is then quite simple:

protected MyJson deserialize(String str) throws IOException {
    String json = StringEscapeUtils.unescapeEcmaScript(str);
    JsonObjectParser parser = (new JacksonFactory()).createJsonObjectParser();
    return parser.parseAndClose(new StringReader(json), MyJson.class);
}

The escapeEcmaScript method isn't complicated, it does following replacement:

  {"'", "\\'"},
  {"\"", "\\\""},
  {"\\", "\\\\"},
  {"/", "\\/"}

But at least is something I don't have to care about.

Tombart
  • 26,066
  • 13
  • 112
  • 120