com.yahoo.text.JSON Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vespajlib Show documentation
Show all versions of vespajlib Show documentation
Library for use in Java components of Vespa. Shared code which do
not fit anywhere else.
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.text;
import com.yahoo.slime.Slime;
import com.yahoo.slime.SlimeUtils;
import java.util.Map;
/**
* Static methods for working with JSON.
*
* @author bratseth
*/
public final class JSON {
/** No instances */
private JSON() {}
/**
* Outputs a map as a JSON 'object' string, provided that the map values
* are either
*
* - String
*
- Number
*
- Any object whose toString returns JSON
*
*/
public static String encode(Map map) {
StringBuilder b = new StringBuilder("{");
for (Map.Entry entry : map.entrySet()) {
b.append("\"").append(escape(entry.getKey())).append("\":");
if (entry.getValue() instanceof String)
b.append("\"").append(escape(entry.getValue().toString())).append("\"");
else // Number, or some other object which returns JSON
b.append(entry.getValue());
b.append(",");
}
if (b.length()>1)
b.setLength(b.length()-1); // remove last comma
b.append("}");
return b.toString();
}
/** Returns the given string as a properly json escaped string */
public static String escape(String s) {
StringBuilder b = null; // lazy create to optimize for "nothing to do" case
for (int i=0; i < s.length(); i = s.offsetByCodePoints(i, 1)) {
final int codepoint = s.codePointAt(i);
if (codepoint == '"') {
if (b == null)
b = new StringBuilder(s.substring(0, i));
b.append('\\');
}
if (b != null)
b.appendCodePoint(codepoint);
}
return b != null ? b.toString() : s;
}
/**
* Test whether two JSON strings are equal, e.g. the order of fields in an object is irrelevant.
*
* When comparing two numbers of the two JSON strings, the result is only guaranteed to be
* correct if (a) both are integers (without fraction and exponent) and each fits in a long, or
* (b) both are non-integers, fits in a double, and are syntactically identical. Examples
* of pairs that may not be equal: 1 and 1.0 (different types), 0.1 and 1e-1, 0.0 and 0.00.
*
* @throws RuntimeException on invalid JSON
*/
public static boolean equals(String left, String right) {
Slime leftSlime = SlimeUtils.jsonToSlimeOrThrow(left);
Slime rightSlime = SlimeUtils.jsonToSlimeOrThrow(right);
return leftSlime.equalTo(rightSlime);
}
public static String canonical(String jsonString) {
return SlimeUtils.jsonToSlimeOrThrow(jsonString).toString();
}
}