I would use a library to create your JSON String for you. Some options are:
- GSON
- Crockford's lib
This will make dealing with escaping much easier. An example (using org.json) would be:
JSONObject obj = new JSONObject();
obj.put("id", userID);
obj.put("type", methoden);
obj.put("msg", msget);
// etc.
final String json = obj.toString(); // <-- JSON string
Answer from jabclab on Stack OverflowI would use a library to create your JSON String for you. Some options are:
- GSON
- Crockford's lib
This will make dealing with escaping much easier. An example (using org.json) would be:
JSONObject obj = new JSONObject();
obj.put("id", userID);
obj.put("type", methoden);
obj.put("msg", msget);
// etc.
final String json = obj.toString(); // <-- JSON string
Apache Commons
If you're already using Apache commons, it provides a static method for this:
StringEscapeUtils.escapeJson("some string")
It converts any string into one that's properly escaped for inclusion in JSON
See the documentation here
java - How should I escape strings in JSON? - Stack Overflow
Escape JSON string in Java - Stack Overflow
How can I prevent my JSON file from being escaped?
Escape double-quotes in JSON string
Ideally, find a JSON library in your language that you can feed some appropriate data structure to, and let it worry about how to escape things. It'll keep you much saner. If for whatever reason you don't have a library in your language, you don't want to use one (I wouldn't suggest this¹), or you're writing a JSON library, read on.
Escape it according to the RFC. JSON is pretty liberal: The only characters you must escape are \, ", and control codes (anything less than U+0020).
This structure of escaping is specific to JSON. You'll need a JSON specific function. All of the escapes can be written as \uXXXX where XXXX is the UTF-16 code unit¹ for that character. There are a few shortcuts, such as \\, which work as well. (And they result in a smaller and clearer output.)
For full details, see the RFC.
¹JSON's escaping is built on JS, so it uses \uXXXX, where XXXX is a UTF-16 code unit. For code points outside the BMP, this means encoding surrogate pairs, which can get a bit hairy. (Or, you can just output the character directly, since JSON's encoded for is Unicode text, and allows these particular characters.)
Extract From Jettison:
public static String quote(String string) {
if (string == null || string.length() == 0) {
return "\"\"";
}
char c = 0;
int i;
int len = string.length();
StringBuilder sb = new StringBuilder(len + 4);
String t;
sb.append('"');
for (i = 0; i < len; i += 1) {
c = string.charAt(i);
switch (c) {
case '\\':
case '"':
sb.append('\\');
sb.append(c);
break;
case '/':
// if (b == '<') {
sb.append('\\');
// }
sb.append(c);
break;
case '\b':
sb.append("\\b");
break;
case '\t':
sb.append("\\t");
break;
case '\n':
sb.append("\\n");
break;
case '\f':
sb.append("\\f");
break;
case '\r':
sb.append("\\r");
break;
default:
if (c < ' ') {
t = "000" + Integer.toHexString(c);
sb.append("\\u" + t.substring(t.length() - 4));
} else {
sb.append(c);
}
}
}
sb.append('"');
return sb.toString();
}
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
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.
I am connecting to an external API and pulling down information.
The information is in JSON format and I can pretty print it to the console just fine. But when saving it as a file, it escapes everything. How can I prevent this?
Request request = new Request.Builder()
.url("https://api.foursquare.com/v3/places/search?categories=19014&near=Athens%2C%20Greece")
.get()
.addHeader("accept", "application/json")
.addHeader("Authorization", System.getenv("foursquare_api_key"))
.build();
Response response = client.newCall(request).execute();
ObjectMapper mapper = new ObjectMapper();
Object jsonString = mapper.readTree(response.body().string()).toPrettyString();
// This looks just fine
System.out.println(jsonString);
// This escapes the file
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
writer.writeValue(new File("src/main/resources/results/greece.athens.json"), jsonString);Any ideas what I am doing wrong?
Thanks!