Skip to content

Instantly share code, notes, and snippets.

@StanSvec
Last active March 19, 2021 03:58
Show Gist options
  • Save StanSvec/ee5edcc04f07643d9c4a9680f44cc8e5 to your computer and use it in GitHub Desktop.
Save StanSvec/ee5edcc04f07643d9c4a9680f44cc8e5 to your computer and use it in GitHub Desktop.
Basic JSON string reading performance benchmark of JSON-P (JSR 374) vs Jackson
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.glassfish.json.JsonUtil;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;
import java.io.StringReader;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static java.util.stream.Collectors.toList;
/**
* <!-- JSR 374 Spec -->
* <dependency>
* <groupId>javax.json</groupId>
* <artifactId>javax.json-api</artifactId>
* <version>1.1</version>
* </dependency>
* <dependency>
* <groupId>org.glassfish</groupId>
* <artifactId>javax.json</artifactId>
* <version>1.1.4</version>
* </dependency>
*
* Jackson version: 2.10.5
*
* Results:
* JSONP JsonUtil: 409 ms
* JSONP Reader: 233 ms
* Jackson: 73 ms
* Jackson To Java Type: 75 ms
*
* JSONP JsonUtil: 2417 ms
* JSONP Reader: 2180 ms
* Jackson: 345 ms
* Jackson To Java Type: 410 ms
*/
public class JsonBench {
private static final String JSON_TEMPLATE = """
{
"stringField": "%s",
"intField": %d,
"doubleField": %f,
"booleanValue": %b,
"nestedObject": {
"f1": "%s",
"f2": "field2"
},
"array1": [%s],
"nested": {"array2": [{"field": "value"}, {"field": "value2"}]}
}
""";
public static void main(String[] args) throws JsonProcessingException {
List<String> jsonStrings = IntStream.range(0, 10000).mapToObj(__ -> createTestJsonStr()).collect(toList());
runForJsr(jsonStrings);
runForJsrReader(jsonStrings);
runForJackson(jsonStrings);
runForJacksonObj(jsonStrings);
System.out.println("-----------------------------------------------------------");
jsonStrings = IntStream.range(0, 150000).mapToObj(__ -> createTestJsonStr()).collect(toList());
runForJsr(jsonStrings);
runForJsrReader(jsonStrings);
runForJackson(jsonStrings);
runForJacksonObj(jsonStrings);
}
public static void runForJsr(List<String> jsonStrings) {
System.out.println(JsonUtil.toJson(createTestJsonStr())); // Do not include potential initialization delay
long start = System.currentTimeMillis();
for (String s : jsonStrings) {
JsonObject jsonObj = (JsonObject) JsonUtil.toJson(s);
readObj(jsonObj);
}
long stop = System.currentTimeMillis();
System.out.println("JSONP JsonUtil: " + (stop - start ) + " ms");
}
public static void runForJsrReader(List<String> jsonStrings) {
try (JsonReader jr = Json.createReader(new StringReader(createTestJsonStr()))) {
System.out.println(jr.readObject()); // Do not include potential initialization delay
}
long start = System.currentTimeMillis();
for (String s : jsonStrings) {
try (JsonReader jr = Json.createReader(new StringReader(s))) {
JsonObject jsonObj = jr.readObject();
readObj(jsonObj);
}
}
long stop = System.currentTimeMillis();
System.out.println("JSONP Reader: " + (stop - start ) + " ms");
}
private static void readObj(JsonObject obj) {
StringBuilder sb = new StringBuilder();
sb.append(obj.getString("stringField")).append(obj.getInt("intField")).append(obj.getJsonObject("nestedObject").getString("f1"));
if (ThreadLocalRandom.current().nextInt() == 6) {
System.out.println(sb.toString());
}
}
public static void runForJackson(List<String> jsonStrings) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.readTree(createTestJsonStr())); // Do not include potential initialization delay
long start = System.currentTimeMillis();
for (String s : jsonStrings) {
JsonNode jsonObj = mapper.readTree(s);
readObj(jsonObj);
}
long stop = System.currentTimeMillis();
System.out.println("Jackson: " + (stop - start ) + " ms");
}
private static void readObj(JsonNode obj) {
StringBuilder sb = new StringBuilder();
sb.append(obj.get("stringField").asText()).append(obj.get("intField").asInt()).append(obj.get("nestedObject").get("f1").asText());
if (ThreadLocalRandom.current().nextInt() == 6) {
System.out.println(sb.toString());
}
}
public static void runForJacksonObj(List<String> jsonStrings) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
System.out.println(mapper.readValue(createTestJsonStr(), JsonAsType.class)); // Do not include potential initialization delay
long start = System.currentTimeMillis();
for (String s : jsonStrings) {
JsonAsType jsonObj = mapper.readValue(s, JsonAsType.class);
readObj(jsonObj);
}
long stop = System.currentTimeMillis();
System.out.println("Jackson To Java Type: " + (stop - start ) + " ms");
}
private static void readObj(JsonAsType obj) {
StringBuilder sb = new StringBuilder();
sb.append(obj.stringField()).append(obj.intField()).append(obj.doubleField()).append(obj.nestedObject().f1());
if (ThreadLocalRandom.current().nextInt() == 6) {
System.out.println(sb.toString());
}
}
public static String createTestJsonStr() {
return JSON_TEMPLATE.formatted(randomStr(), (int) randomNumber(), randomNumber(), ((int)randomNumber()) % 2 == 0, randomStr(), randomSeq());
}
public static String randomStr() {
return Long.toHexString(ThreadLocalRandom.current().nextLong());
}
public static double randomNumber() {
return ThreadLocalRandom.current().nextDouble() * 100;
}
public static String randomSeq() {
int length = ThreadLocalRandom.current().nextInt(10);
return ThreadLocalRandom.current().ints(length).mapToObj(Objects::toString).collect(Collectors.joining(","));
}
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
static record JsonAsType(@JsonProperty("stringField") String stringField,
@JsonProperty("intField") int intField,
@JsonProperty("doubleField") double doubleField,
@JsonProperty("booleanValue") boolean booleanValue,
@JsonProperty("nestedObject") Nested nestedObject,
@JsonProperty("array1") List<String> array1) {}
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
static record Nested(@JsonProperty("f1") String f1, @JsonProperty("f2") String f2) {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment