Skip to content

Commit 686f51a

Browse files
Add JSON component (#7973)
* feat(json): Add JSON component * feat(internal-api): Remove Strings toJson and escapeToJson methods * feat(ci-visibility): Migrate to JSON component * feat(junit-4.10): Migrate to JSON component * feat(junit-5.3): Migrate to JSON component * feat(karate): Migrate to JSON component * feat(testng): Migrate to JSON component * feat(bootstrap): Migrate to JSON component * feat(json): Improve structure performance
1 parent d2c8a74 commit 686f51a

File tree

41 files changed

+1291
-699
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1291
-699
lines changed

components/json/build.gradle.kts

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
plugins {
2+
id("me.champeau.jmh")
3+
}
4+
5+
apply(from = "$rootDir/gradle/java.gradle")
6+
7+
jmh {
8+
version = "1.28"
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package datadog.json;
2+
3+
import static java.util.concurrent.TimeUnit.MICROSECONDS;
4+
import static org.openjdk.jmh.annotations.Mode.AverageTime;
5+
6+
import org.openjdk.jmh.annotations.Benchmark;
7+
import org.openjdk.jmh.annotations.BenchmarkMode;
8+
import org.openjdk.jmh.annotations.Fork;
9+
import org.openjdk.jmh.annotations.OutputTimeUnit;
10+
import org.openjdk.jmh.infra.Blackhole;
11+
12+
@BenchmarkMode(AverageTime)
13+
@OutputTimeUnit(MICROSECONDS)
14+
@Fork(value = 1)
15+
@SuppressWarnings("unused")
16+
public class JsonWriterBenchmark {
17+
@Benchmark
18+
public void writeSimpleArray(Blackhole blackhole) {
19+
try (JsonWriter writer = new JsonWriter()) {
20+
writer
21+
.beginArray()
22+
.beginObject()
23+
.name("true")
24+
.value(true)
25+
.endObject()
26+
.beginObject()
27+
.name("false")
28+
.value(false)
29+
.endObject()
30+
.endArray();
31+
blackhole.consume(writer.toString());
32+
}
33+
}
34+
35+
@Benchmark
36+
public void writeComplexArray(Blackhole blackhole) {
37+
try (JsonWriter writer = new JsonWriter()) {
38+
writer
39+
.beginArray()
40+
.value("first level")
41+
.beginArray()
42+
.value("second level")
43+
.beginArray()
44+
.value("third level")
45+
.beginObject()
46+
.name("key")
47+
.value("value")
48+
.endObject()
49+
.beginObject()
50+
.name("key")
51+
.value("value")
52+
.endObject()
53+
.endArray() // second level
54+
.beginObject()
55+
.name("key")
56+
.value("value")
57+
.endObject()
58+
.endArray() // first level
59+
.beginObject()
60+
.name("key")
61+
.value("value")
62+
.endObject()
63+
.value("last value")
64+
.endArray();
65+
blackhole.consume(writer.toString());
66+
}
67+
}
68+
69+
@Benchmark
70+
public void writeComplexObject(Blackhole blackhole) {
71+
try (JsonWriter writer = new JsonWriter()) {
72+
writer
73+
.beginObject()
74+
.name("attrs")
75+
.beginObject()
76+
.name("attr1")
77+
.value("value1")
78+
.name("attr2")
79+
.value("value2")
80+
.endObject()
81+
.name("data")
82+
.beginArray()
83+
.beginObject()
84+
.name("x")
85+
.value(1)
86+
.name("y")
87+
.value(12.3)
88+
.endObject()
89+
.beginObject()
90+
.name("x")
91+
.value(2)
92+
.name("y")
93+
.value(4.56)
94+
.endObject()
95+
.beginObject()
96+
.name("x")
97+
.value(3)
98+
.name("y")
99+
.value(789)
100+
.endObject()
101+
.endArray()
102+
.endObject();
103+
blackhole.consume(writer.toString());
104+
}
105+
}
106+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package datadog.json;
2+
3+
import java.util.Collection;
4+
import java.util.Map;
5+
6+
/** Utility class for simple Java structure mapping into JSON strings. */
7+
public final class JsonMapper {
8+
9+
private JsonMapper() {}
10+
11+
/**
12+
* Converts a {@link String} to a JSON string.
13+
*
14+
* @param string The string to convert.
15+
* @return The converted JSON string.
16+
*/
17+
public static String toJson(String string) {
18+
if (string == null || string.isEmpty()) {
19+
return "";
20+
}
21+
try (JsonWriter writer = new JsonWriter()) {
22+
writer.value(string);
23+
return writer.toString();
24+
}
25+
}
26+
27+
/**
28+
* Converts a {@link Map} to a JSON object.
29+
*
30+
* @param map The map to convert.
31+
* @return The converted JSON object as Java string.
32+
*/
33+
public static String toJson(Map<String, ?> map) {
34+
if (map == null || map.isEmpty()) {
35+
return "{}";
36+
}
37+
try (JsonWriter writer = new JsonWriter()) {
38+
writer.beginObject();
39+
for (Map.Entry<String, ?> entry : map.entrySet()) {
40+
writer.name(entry.getKey());
41+
Object value = entry.getValue();
42+
if (value == null) {
43+
writer.nullValue();
44+
} else if (value instanceof String) {
45+
writer.value((String) value);
46+
} else if (value instanceof Double) {
47+
writer.value((Double) value);
48+
} else if (value instanceof Float) {
49+
writer.value((Float) value);
50+
} else if (value instanceof Long) {
51+
writer.value((Long) value);
52+
} else if (value instanceof Integer) {
53+
writer.value((Integer) value);
54+
} else if (value instanceof Boolean) {
55+
writer.value((Boolean) value);
56+
} else {
57+
writer.value(value.toString());
58+
}
59+
}
60+
writer.endObject();
61+
return writer.toString();
62+
}
63+
}
64+
65+
/**
66+
* Converts a {@link Iterable<String>} to a JSON array.
67+
*
68+
* @param items The iterable to convert.
69+
* @return The converted JSON array as Java string.
70+
*/
71+
@SuppressWarnings("DuplicatedCode")
72+
public static String toJson(Collection<String> items) {
73+
if (items == null || items.isEmpty()) {
74+
return "[]";
75+
}
76+
try (JsonWriter writer = new JsonWriter()) {
77+
writer.beginArray();
78+
for (String item : items) {
79+
writer.value(item);
80+
}
81+
writer.endArray();
82+
return writer.toString();
83+
}
84+
}
85+
86+
/**
87+
* Converts a String array to a JSON array.
88+
*
89+
* @param items The array to convert.
90+
* @return The converted JSON array as Java string.
91+
*/
92+
@SuppressWarnings("DuplicatedCode")
93+
public static String toJson(String[] items) {
94+
if (items == null) {
95+
return "[]";
96+
}
97+
try (JsonWriter writer = new JsonWriter()) {
98+
writer.beginArray();
99+
for (String item : items) {
100+
writer.value(item);
101+
}
102+
writer.endArray();
103+
return writer.toString();
104+
}
105+
}
106+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package datadog.json;
2+
3+
/** The {@link JsonStructure} keeps track of JSON value being built. */
4+
interface JsonStructure {
5+
/**
6+
* Begins an object.
7+
*
8+
* @throws IllegalStateException if the object can not be started at this position.
9+
*/
10+
void beginObject();
11+
12+
/**
13+
* Checks whether the current position is within an object.
14+
*
15+
* @return {@code true} if the current position is within an object, {@code false} otherwise.
16+
*/
17+
boolean objectStarted();
18+
19+
/**
20+
* Ends the current object.
21+
*
22+
* @throws IllegalStateException if the current position is not within an object.
23+
*/
24+
void endObject();
25+
26+
/** Begins an array. */
27+
void beginArray();
28+
29+
/**
30+
* Checks whether the current position is within an array.
31+
*
32+
* @return {@code true} if the current position is within an array, {@code false} otherwise.
33+
*/
34+
boolean arrayStarted();
35+
36+
/**
37+
* Ends the current array.
38+
*
39+
* @throws IllegalStateException if the current position is not within an array.
40+
*/
41+
void endArray();
42+
43+
/**
44+
* Adds a name to the current object.
45+
*
46+
* @throws IllegalStateException if the current position is not within an object.
47+
*/
48+
void addName();
49+
50+
/**
51+
* Adds a value.
52+
*
53+
* @throws IllegalStateException if the current position can not have a value.
54+
*/
55+
void addValue();
56+
}

0 commit comments

Comments
 (0)