JSON Small and Fast Parser - A lightweight, high-performance JSON processing library for Java
—
JSON-Smart provides extensive configuration options through JSONStyle for controlling JSON output formatting, compression levels, and parser behavior. This document covers all configuration aspects for both serialization and parsing.
JSONStyle controls how JSON is formatted during serialization, offering various compression levels and formatting options.
public static final JSONStyle NO_COMPRESS;
public static final JSONStyle MAX_COMPRESS;
public static final JSONStyle LT_COMPRESS;Three predefined formatting styles for common use cases.
JSONObject obj = new JSONObject()
.appendField("name", "John Doe")
.appendField("age", 30)
.appendField("active", true);
// No compression - readable formatting
String readable = obj.toJSONString(JSONStyle.NO_COMPRESS);
// {"name" : "John Doe", "age" : 30, "active" : true}
// Maximum compression - minimal size
String compressed = obj.toJSONString(JSONStyle.MAX_COMPRESS);
// {name:"John Doe",age:30,active:true}
// Light compression - balanced
String balanced = obj.toJSONString(JSONStyle.LT_COMPRESS);
// {"name":"John Doe","age":30,"active":true}public static final int FLAG_PROTECT_KEYS = 1;
public static final int FLAG_PROTECT_4WEB = 2;
public static final int FLAG_PROTECT_VALUES = 4;
public static final int FLAG_AGRESSIVE = 8;
public static final int FLAG_IGNORE_NULL = 16;Individual flags that control specific formatting behaviors:
public JSONStyle();
public JSONStyle(int FLAG);Create custom formatting styles.
// Default style
JSONStyle defaultStyle = new JSONStyle();
// Custom style with specific flags
JSONStyle customStyle = new JSONStyle(
JSONStyle.FLAG_PROTECT_KEYS | JSONStyle.FLAG_IGNORE_NULL
);
// Multiple flags combined
int webSafeFlags = JSONStyle.FLAG_PROTECT_KEYS |
JSONStyle.FLAG_PROTECT_4WEB |
JSONStyle.FLAG_IGNORE_NULL;
JSONStyle webSafe = new JSONStyle(webSafeFlags);public boolean protectKeys();
public boolean protectValues();
public boolean protect4Web();
public boolean ignoreNull();
public boolean indent();
public boolean mustProtectKey(String s);
public boolean mustProtectValue(String s);Query current configuration and test protection requirements.
JSONStyle style = new JSONStyle(JSONStyle.FLAG_PROTECT_KEYS | JSONStyle.FLAG_IGNORE_NULL);
// Check configuration
boolean quotesKeys = style.protectKeys(); // true
boolean skipsNull = style.ignoreNull(); // true
boolean indented = style.indent(); // false
// Test specific values
boolean needsQuotes = style.mustProtectKey("validKey"); // true (always protect when flag set)
boolean valueNeedsQuotes = style.mustProtectValue("simple"); // depends on flag and contentJSONObject obj = new JSONObject()
.appendField("simpleKey", "value")
.appendField("key with spaces", "value")
.appendField("123numeric", "value")
.appendField("key-with-dashes", "value");
// Default style - quotes only when necessary
String normal = obj.toJSONString();
// {simpleKey:"value","key with spaces":"value","123numeric":"value","key-with-dashes":"value"}
// Always protect keys
JSONStyle protectKeys = new JSONStyle(JSONStyle.FLAG_PROTECT_KEYS);
String quoted = obj.toJSONString(protectKeys);
// {"simpleKey":"value","key with spaces":"value","123numeric":"value","key-with-dashes":"value"}JSONObject obj = new JSONObject()
.appendField("string", "simple")
.appendField("number", 42)
.appendField("boolean", true)
.appendField("special", "string with \"quotes\" and \n newlines");
// Default style
String normal = obj.toJSONString();
// {string:simple,number:42,boolean:true,special:"string with \"quotes\" and \n newlines"}
// Always protect string values
JSONStyle protectValues = new JSONStyle(JSONStyle.FLAG_PROTECT_VALUES);
String quoted = obj.toJSONString(protectValues);
// {string:"simple",number:42,boolean:true,special:"string with \"quotes\" and \n newlines"}JSONObject obj = new JSONObject()
.appendField("name", "John")
.appendField("middle", null)
.appendField("age", 30)
.appendField("email", null);
// Default style - includes nulls
String withNulls = obj.toJSONString();
// {name:"John",middle:null,age:30,email:null}
// Ignore null values
JSONStyle ignoreNull = new JSONStyle(JSONStyle.FLAG_IGNORE_NULL);
String noNulls = obj.toJSONString(ignoreNull);
// {name:"John",age:30}JSONObject obj = new JSONObject()
.appendField("html", "<script>alert('xss')</script>")
.appendField("path", "/api/users")
.appendField("callback", "jsonp_callback_123");
// Default style
String normal = obj.toJSONString();
// {html:"<script>alert('xss')</script>",path:"/api/users",callback:"jsonp_callback_123"}
// Web-safe escaping
JSONStyle webSafe = new JSONStyle(JSONStyle.FLAG_PROTECT_4WEB);
String safe = obj.toJSONString(webSafe);
// {html:"\\u003cscript\\u003ealert('xss')\\u003c\\/script\\u003e",path:"\\/api\\/users",callback:"jsonp_callback_123"}JSONStyle provides methods for writing JSON output with specific formatting.
public void writeString(Appendable out, String value) throws IOException;
public void escape(String s, Appendable out);Write strings with appropriate escaping and quoting.
JSONStyle style = new JSONStyle(JSONStyle.FLAG_PROTECT_VALUES);
StringBuilder sb = new StringBuilder();
// Write quoted string
style.writeString(sb, "Hello World");
System.out.println(sb.toString()); // "Hello World"
// Write with escaping
sb.setLength(0);
style.escape("Text with \"quotes\"", sb);
System.out.println(sb.toString()); // Text with \"quotes\"public void objectStart(Appendable out) throws IOException;
public void objectStop(Appendable out) throws IOException;
public void objectFirstStart(Appendable out) throws IOException;
public void objectNext(Appendable out) throws IOException;
public void objectElmStop(Appendable out) throws IOException;
public void objectEndOfKey(Appendable out) throws IOException;
public void arrayStart(Appendable out) throws IOException;
public void arrayStop(Appendable out) throws IOException;
public void arrayfirstObject(Appendable out) throws IOException;
public void arrayNextElm(Appendable out) throws IOException;
public void arrayObjectEnd(Appendable out) throws IOException;Low-level methods for manual JSON construction with consistent formatting.
JSONStyle style = JSONStyle.NO_COMPRESS;
StringBuilder json = new StringBuilder();
// Manual object construction
style.objectStart(json); // {
style.objectFirstStart(json); //
json.append("\"name\"");
style.objectEndOfKey(json); // :
style.writeString(json, "John"); // "John"
style.objectNext(json); // ,
json.append("\"age\"");
style.objectEndOfKey(json); // :
json.append("30");
style.objectElmStop(json); //
style.objectStop(json); // }
System.out.println(json.toString()); // {"name" : "John", "age" : 30}// Create highly compressed style for APIs
public class APICompressionStyle extends JSONStyle {
public APICompressionStyle() {
super(FLAG_AGRESSIVE | FLAG_IGNORE_NULL | FLAG_PROTECT_4WEB);
}
@Override
public boolean mustProtectKey(String key) {
// Never protect keys that are simple identifiers
if (key.matches("^[a-zA-Z_][a-zA-Z0-9_]*$")) {
return false;
}
return super.mustProtectKey(key);
}
@Override
public boolean mustProtectValue(String value) {
// Don't protect simple numeric strings
if (value.matches("^\\d+$")) {
return false;
}
return super.mustProtectValue(value);
}
}
// Usage
JSONStyle apiStyle = new APICompressionStyle();
JSONObject data = new JSONObject()
.appendField("userId", "12345")
.appendField("status", "active")
.appendField("count", null);
String compressed = data.toJSONString(apiStyle);
// {userId:12345,status:active} (null ignored, minimal quotes)public class DebugJSONStyle extends JSONStyle {
public DebugJSONStyle() {
super(FLAG_PROTECT_KEYS | FLAG_PROTECT_VALUES);
}
@Override
public void objectStart(Appendable out) throws IOException {
out.append("{\n ");
}
@Override
public void objectStop(Appendable out) throws IOException {
out.append("\n}");
}
@Override
public void objectNext(Appendable out) throws IOException {
out.append(",\n ");
}
@Override
public void objectEndOfKey(Appendable out) throws IOException {
out.append(" : ");
}
@Override
public void arrayStart(Appendable out) throws IOException {
out.append("[\n ");
}
@Override
public void arrayStop(Appendable out) throws IOException {
out.append("\n ]");
}
@Override
public void arrayNextElm(Appendable out) throws IOException {
out.append(",\n ");
}
}
// Usage
JSONStyle debugStyle = new DebugJSONStyle();
JSONObject obj = new JSONObject()
.appendField("name", "John")
.appendField("items", Arrays.asList("a", "b", "c"));
String formatted = obj.toJSONString(debugStyle);
/*
{
"name" : "John",
"items" : [
"a",
"b",
"c"
]
}
*/While JSONStyle controls output formatting, parser configuration is handled through JSONParser mode flags.
// Strict web API parsing
int webApiMode = JSONParser.MODE_RFC4627 | JSONParser.REJECT_127_CHAR;
JSONParser webParser = new JSONParser(webApiMode);
// Lenient file parsing
int fileMode = JSONParser.MODE_PERMISSIVE |
JSONParser.ACCEPT_SIMPLE_QUOTE |
JSONParser.ACCEPT_USELESS_COMMA;
JSONParser fileParser = new JSONParser(fileMode);
// High-precision financial parsing
int financialMode = JSONParser.MODE_PERMISSIVE |
JSONParser.USE_HI_PRECISION_FLOAT |
JSONParser.BIG_DIGIT_UNRESTRICTED;
JSONParser financialParser = new JSONParser(financialMode);public class ConfigurationValidator {
public static void validateStyleConfiguration(JSONStyle style) {
System.out.println("Style Configuration:");
System.out.println(" Protect Keys: " + style.protectKeys());
System.out.println(" Protect Values: " + style.protectValues());
System.out.println(" Web Safe: " + style.protect4Web());
System.out.println(" Ignore Null: " + style.ignoreNull());
System.out.println(" Indent: " + style.indent());
}
public static void testStyleOutput(JSONStyle style) {
JSONObject testObj = new JSONObject()
.appendField("simpleKey", "simpleValue")
.appendField("key with spaces", "value with \"quotes\"")
.appendField("nullValue", null)
.appendField("number", 42)
.appendField("htmlContent", "<script>alert('test')</script>");
String output = testObj.toJSONString(style);
System.out.println("Output: " + output);
System.out.println("Length: " + output.length());
}
}
// Usage
JSONStyle customStyle = new JSONStyle(
JSONStyle.FLAG_PROTECT_KEYS |
JSONStyle.FLAG_IGNORE_NULL |
JSONStyle.FLAG_PROTECT_4WEB
);
ConfigurationValidator.validateStyleConfiguration(customStyle);
ConfigurationValidator.testStyleOutput(customStyle);// Fastest serialization - minimal processing
JSONStyle fastest = JSONStyle.MAX_COMPRESS;
// Memory efficient - excludes nulls
JSONStyle memoryEfficient = new JSONStyle(JSONStyle.FLAG_IGNORE_NULL);
// Network efficient - maximum compression + null exclusion
JSONStyle networkEfficient = new JSONStyle(
JSONStyle.FLAG_AGRESSIVE | JSONStyle.FLAG_IGNORE_NULL
);
// Benchmark different styles
public void benchmarkStyles(Object testData, int iterations) {
JSONStyle[] styles = {
JSONStyle.NO_COMPRESS,
JSONStyle.LT_COMPRESS,
JSONStyle.MAX_COMPRESS,
networkEfficient
};
for (JSONStyle style : styles) {
long start = System.nanoTime();
for (int i = 0; i < iterations; i++) {
String json = JSONValue.toJSONString(testData, style);
}
long end = System.nanoTime();
String sample = JSONValue.toJSONString(testData, style);
System.out.printf("Style: %s, Time: %dms, Size: %d bytes%n",
style.getClass().getSimpleName(),
(end - start) / 1_000_000,
sample.length());
}
}public class StyleCache {
private static final Map<String, JSONStyle> STYLE_CACHE = new ConcurrentHashMap<>();
public static JSONStyle getOrCreateStyle(String name, int flags) {
return STYLE_CACHE.computeIfAbsent(name, k -> new JSONStyle(flags));
}
// Predefined cached styles
public static final JSONStyle WEB_API_STYLE = getOrCreateStyle("webApi",
JSONStyle.FLAG_PROTECT_KEYS | JSONStyle.FLAG_PROTECT_4WEB | JSONStyle.FLAG_IGNORE_NULL);
public static final JSONStyle MOBILE_API_STYLE = getOrCreateStyle("mobileApi",
JSONStyle.FLAG_AGRESSIVE | JSONStyle.FLAG_IGNORE_NULL);
public static final JSONStyle DEBUG_STYLE = getOrCreateStyle("debug",
JSONStyle.FLAG_PROTECT_KEYS | JSONStyle.FLAG_PROTECT_VALUES);
}
// Usage
String webJson = JSONValue.toJSONString(data, StyleCache.WEB_API_STYLE);
String mobileJson = JSONValue.toJSONString(data, StyleCache.MOBILE_API_STYLE);public class RestApiConfig {
// Input parsing - strict but allow common relaxations
private static final int API_PARSER_MODE =
JSONParser.MODE_RFC4627 |
JSONParser.ACCEPT_TAILLING_SPACE |
JSONParser.USE_INTEGER_STORAGE;
// Output formatting - web-safe and compact
private static final JSONStyle API_OUTPUT_STYLE = new JSONStyle(
JSONStyle.FLAG_PROTECT_KEYS |
JSONStyle.FLAG_PROTECT_4WEB |
JSONStyle.FLAG_IGNORE_NULL
);
public static final JSONParser API_PARSER = new JSONParser(API_PARSER_MODE);
public static <T> T parseRequest(String json, Class<T> type) throws ParseException {
return API_PARSER.parse(json, type);
}
public static String formatResponse(Object data) {
return JSONValue.toJSONString(data, API_OUTPUT_STYLE);
}
}
// Usage
try {
MyRequest request = RestApiConfig.parseRequest(requestJson, MyRequest.class);
MyResponse response = processRequest(request);
String responseJson = RestApiConfig.formatResponse(response);
return responseJson;
} catch (ParseException e) {
String errorJson = RestApiConfig.formatResponse(
Map.of("error", "Invalid JSON", "details", e.getMessage())
);
return errorJson;
}public class FileProcessingConfig {
// Lenient parsing for user-generated files
private static final int FILE_PARSER_MODE =
JSONParser.MODE_PERMISSIVE |
JSONParser.ACCEPT_SIMPLE_QUOTE |
JSONParser.ACCEPT_USELESS_COMMA |
JSONParser.ACCEPT_LEADING_ZERO |
JSONParser.IGNORE_CONTROL_CHAR;
// Readable output for file generation
private static final JSONStyle FILE_OUTPUT_STYLE = JSONStyle.NO_COMPRESS;
public static final JSONParser FILE_PARSER = new JSONParser(FILE_PARSER_MODE);
public static Object parseFile(Path filePath) throws IOException, ParseException {
try (Reader reader = Files.newBufferedReader(filePath)) {
return FILE_PARSER.parse(reader);
}
}
public static void writeFile(Object data, Path filePath) throws IOException {
try (Writer writer = Files.newBufferedWriter(filePath)) {
JSONValue.writeJSONString(data, writer, FILE_OUTPUT_STYLE);
}
}
}public class ConfigurationTester {
public static void testConfiguration(String name, JSONParser parser, JSONStyle style) {
System.out.println("Testing configuration: " + name);
// Test various JSON inputs
String[] testInputs = {
"{\"valid\": \"json\"}",
"{'single': 'quotes'}",
"{\"trailing\": \"comma\",}",
"{\"leading\": 007}",
"{\"unicode\": \"\\u0041\"}",
"{\"null\": null}",
"{\"number\": 123.456789012345678901234567890}"
};
for (String input : testInputs) {
try {
Object parsed = parser.parse(input);
String output = JSONValue.toJSONString(parsed, style);
System.out.printf(" ✓ %s -> %s%n", input, output);
} catch (ParseException e) {
System.out.printf(" ✗ %s -> ERROR: %s%n", input, e.getMessage());
}
}
System.out.println();
}
public static void main(String[] args) {
// Test different configurations
testConfiguration("Strict Web API",
new JSONParser(JSONParser.MODE_RFC4627),
new JSONStyle(JSONStyle.FLAG_PROTECT_KEYS | JSONStyle.FLAG_PROTECT_4WEB));
testConfiguration("Lenient File Processing",
new JSONParser(JSONParser.MODE_PERMISSIVE),
JSONStyle.NO_COMPRESS);
testConfiguration("High Performance API",
new JSONParser(JSONParser.MODE_PERMISSIVE),
JSONStyle.MAX_COMPRESS);
}
}Install with Tessl CLI
npx tessl i tessl/maven-net-minidev--json-smart