Skip to content

Commit ce3fe98

Browse files
committed
improve ser
1 parent 65121e4 commit ce3fe98

19 files changed

Lines changed: 299 additions & 204 deletions

demo/src/test/java/com/jsoniter/demo/ObjectOutput.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.io.ByteArrayOutputStream;
2020
import java.io.IOException;
21+
import java.util.Arrays;
22+
import java.util.List;
2123

2224
@State(Scope.Thread)
2325
public class ObjectOutput {
@@ -34,7 +36,7 @@ public class ObjectOutput {
3436
@CompiledJson
3537
public static class TestObject {
3638
public String field1;
37-
public String field2;
39+
public List<String> field2;
3840
}
3941

4042
public static void main(String[] args) throws Exception {
@@ -69,7 +71,7 @@ public void benchSetup(BenchmarkParams params) {
6971
dslJson = new DslJson();
7072
testObject = new TestObject();
7173
testObject.field1 = "hello";
72-
testObject.field2 = "world";
74+
testObject.field2 = Arrays.asList("hello", "hello");
7375
typeLiteral = TypeLiteral.create(TestObject.class);
7476
jsonWriter = new JsonWriter();
7577
}
@@ -82,18 +84,18 @@ public void jsoniter() throws IOException {
8284
stream.flush();
8385
}
8486

85-
// @Benchmark
87+
// @Benchmark
8688
public void jsoniter_easy_mode(Blackhole bh) throws IOException {
8789
bh.consume(JsonStream.serialize(testObject));
8890
}
8991

90-
// @Benchmark
92+
// @Benchmark
9193
public void jackson() throws IOException {
9294
baos.reset();
9395
objectMapper.writeValue(baos, testObject);
9496
}
9597

96-
// @Benchmark
98+
@Benchmark
9799
public void dsljson() throws IOException {
98100
baos.reset();
99101
jsonWriter.reset();

demo/src/test/java/com/jsoniter/demo/StringOutput.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33

44
import com.dslplatform.json.DslJson;
5+
import com.dslplatform.json.JsonWriter;
56
import com.fasterxml.jackson.core.JsonGenerator;
67
import com.fasterxml.jackson.databind.ObjectMapper;
78
import com.jsoniter.output.JsonStream;
@@ -21,6 +22,7 @@ public class StringOutput {
2122
private JsonStream stream;
2223
private byte[] buffer;
2324
private DslJson dslJson;
25+
private JsonWriter jsonWriter;
2426

2527
public static void main(String[] args) throws Exception {
2628
Main.main(new String[]{
@@ -50,6 +52,7 @@ public void benchSetup(BenchmarkParams params) {
5052
stream = new JsonStream(baos, 4096);
5153
buffer = new byte[4096];
5254
dslJson = new DslJson();
55+
jsonWriter = new JsonWriter();
5356
}
5457

5558
@Benchmark
@@ -69,6 +72,8 @@ public void jackson() throws IOException {
6972
@Benchmark
7073
public void dsljson() throws IOException {
7174
baos.reset();
72-
dslJson.serialize("hello world ~~ hello 中文 ~~~", baos);
75+
jsonWriter.reset();
76+
jsonWriter.write("hello world ~~ hello 中文 ~~~");
77+
jsonWriter.toStream(baos);
7378
}
7479
}

demo/src/test/java/json/ExternalSerialization.java

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,23 @@ static void __serializeJsonObjectMinimal(final com.jsoniter.demo.ObjectOutput.Te
5555
sw.writeString(self.field1);
5656
}
5757

58-
if (self.field2 != null) {
58+
final java.util.List<String> _tmp_field2_ = self.field2;
59+
if(_tmp_field2_ != null && _tmp_field2_.size() != 0) {
5960
if(hasWrittenProperty) sw.writeByte(com.dslplatform.json.JsonWriter.COMMA);
6061
hasWrittenProperty = true;
61-
sw.writeAscii("\"field2\":", 9);
62-
sw.writeString(self.field2);
62+
sw.writeAscii("\"field2\":[", 10);
63+
com.dslplatform.json.StringConverter.serializeNullable(_tmp_field2_.get(0), sw);
64+
for(int i = 1; i < _tmp_field2_.size(); i++) {
65+
sw.writeByte(com.dslplatform.json.JsonWriter.COMMA);
66+
com.dslplatform.json.StringConverter.serializeNullable(_tmp_field2_.get(i), sw);
6367
}
68+
sw.writeByte(com.dslplatform.json.JsonWriter.ARRAY_END);
69+
}
70+
else if(self.field2 != null) {
71+
if(hasWrittenProperty) sw.writeByte(com.dslplatform.json.JsonWriter.COMMA);
72+
hasWrittenProperty = true;
73+
sw.writeAscii("\"field2\":[]", 11);
74+
}
6475
}
6576

6677
static void __serializeJsonObjectFull(final com.jsoniter.demo.ObjectOutput.TestObject self, com.dslplatform.json.JsonWriter sw, boolean hasWrittenProperty) {
@@ -74,13 +85,18 @@ static void __serializeJsonObjectFull(final com.jsoniter.demo.ObjectOutput.TestO
7485
sw.writeAscii("\"field1\":null", 13);
7586
}
7687

77-
78-
if (self.field2 != null) {
79-
sw.writeAscii(",\"field2\":", 10);
80-
sw.writeString(self.field2);
81-
} else {
82-
sw.writeAscii(",\"field2\":null", 14);
88+
final java.util.List<String> _tmp_field2_ = self.field2;
89+
if(_tmp_field2_ != null && _tmp_field2_.size() != 0) {
90+
sw.writeAscii(",\"field2\":[", 11);
91+
com.dslplatform.json.StringConverter.serializeNullable(_tmp_field2_.get(0), sw);
92+
for(int i = 1; i < _tmp_field2_.size(); i++) {
93+
sw.writeByte(com.dslplatform.json.JsonWriter.COMMA);
94+
com.dslplatform.json.StringConverter.serializeNullable(_tmp_field2_.get(i), sw);
8395
}
96+
sw.writeByte(com.dslplatform.json.JsonWriter.ARRAY_END);
97+
}
98+
else if(self.field2 != null) sw.writeAscii(",\"field2\":[]", 12);
99+
else sw.writeAscii(",\"field2\":null", 14);
84100
}
85101

86102
public static final com.dslplatform.json.JsonReader.ReadObject<com.jsoniter.demo.ObjectOutput.TestObject> JSON_READER_struct0 = new com.dslplatform.json.JsonReader.ReadObject<com.jsoniter.demo.ObjectOutput.TestObject>() {
@@ -108,7 +124,7 @@ static com.jsoniter.demo.ObjectOutput.TestObject deserializestruct0(final com.ds
108124
static void deserialize(final com.jsoniter.demo.ObjectOutput.TestObject instance, final com.dslplatform.json.JsonReader reader) throws java.io.IOException {
109125

110126
String _field1_ = null;
111-
String _field2_ = null;
127+
java.util.List<String> _field2_ = null;
112128
byte nextToken = reader.last();
113129
if(nextToken != '}') {
114130
int nameHash = reader.fillName();
@@ -127,8 +143,16 @@ static void deserialize(final com.jsoniter.demo.ObjectOutput.TestObject instance
127143
nextToken = reader.getNextToken();
128144
break;
129145
case 1195428815:
130-
_field2_ = com.dslplatform.json.StringConverter.deserialize(reader);
131-
nextToken = reader.getNextToken();
146+
147+
if (nextToken == '[') {
148+
nextToken = reader.getNextToken();
149+
if (nextToken != ']') {
150+
java.util.List<String> __res = com.dslplatform.json.StringConverter.deserializeNullableCollection(reader);
151+
_field2_ = __res;
152+
}
153+
nextToken = reader.getNextToken();
154+
}
155+
else throw new java.io.IOException("Expecting '[' at position " + reader.positionInStream() + ". Found " + (char)nextToken);
132156
break;
133157
default:
134158
nextToken = reader.skip();
@@ -154,8 +178,16 @@ static void deserialize(final com.jsoniter.demo.ObjectOutput.TestObject instance
154178
nextToken = reader.getNextToken();
155179
break;
156180
case 1195428815:
157-
_field2_ = com.dslplatform.json.StringConverter.deserialize(reader);
158-
nextToken = reader.getNextToken();
181+
182+
if (nextToken == '[') {
183+
nextToken = reader.getNextToken();
184+
if (nextToken != ']') {
185+
java.util.List<String> __res = com.dslplatform.json.StringConverter.deserializeNullableCollection(reader);
186+
_field2_ = __res;
187+
}
188+
nextToken = reader.getNextToken();
189+
}
190+
else throw new java.io.IOException("Expecting '[' at position " + reader.positionInStream() + ". Found " + (char)nextToken);
159191
break;
160192
default:
161193
nextToken = reader.skip();

src/main/java/com/jsoniter/output/Codegen.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class Codegen {
1919
private static EncodingMode mode = EncodingMode.REFLECTION_MODE;
2020
static boolean isDoingStaticCodegen;
2121
// only read/write when generating code with synchronized protection
22-
private final static Set<String> generatedClassNames = new HashSet<String>();
22+
private final static Map<String, CodegenResult> generatedSources = new HashMap<String, CodegenResult>();
2323
private volatile static Map<String, Encoder> reflectionEncoders = new HashMap<String, Encoder>();
2424

2525
static {
@@ -114,13 +114,15 @@ private static synchronized Encoder gen(String cacheKey, Type type) {
114114
throw new JsonException("static gen should provide the encoder we need, but failed to create the encoder", e);
115115
}
116116
}
117-
String source = genSource(clazz, typeArgs);
117+
CodegenResult source = genSource(clazz, typeArgs);
118118
if ("true".equals(System.getenv("JSONITER_DEBUG"))) {
119119
System.out.println(">>> " + cacheKey);
120+
System.out.println("prelude: " + source.prelude);
120121
System.out.println(source);
122+
System.out.println("epilogue: " + source.epilogue);
121123
}
122124
try {
123-
generatedClassNames.add(cacheKey);
125+
generatedSources.put(cacheKey, source);
124126
if (isDoingStaticCodegen) {
125127
staticGen(clazz, cacheKey, source);
126128
} else {
@@ -136,18 +138,19 @@ private static synchronized Encoder gen(String cacheKey, Type type) {
136138
}
137139
}
138140

139-
public static boolean canStaticAccess(String cacheKey) {
140-
return generatedClassNames.contains(cacheKey);
141+
public static CodegenResult getGeneratedSource(String cacheKey) {
142+
return generatedSources.get(cacheKey);
141143
}
142144

143-
private static void staticGen(Class clazz, String cacheKey, String source) throws IOException {
145+
private static void staticGen(Class clazz, String cacheKey, CodegenResult source) throws IOException {
144146
createDir(cacheKey);
145147
String fileName = cacheKey.replace('.', '/') + ".java";
146148
FileOutputStream fileOutputStream = new FileOutputStream(fileName);
147149
try {
148150
OutputStreamWriter writer = new OutputStreamWriter(fileOutputStream);
149151
try {
150-
staticGen(clazz, cacheKey, writer, source);
152+
throw new UnsupportedOperationException();
153+
// staticGen(clazz, cacheKey, writer, source);
151154
} finally {
152155
writer.close();
153156
}
@@ -179,7 +182,7 @@ private static void createDir(String cacheKey) {
179182
}
180183
}
181184

182-
private static String genSource(Class clazz, Type[] typeArgs) {
185+
private static CodegenResult genSource(Class clazz, Type[] typeArgs) {
183186
if (clazz.isArray()) {
184187
return CodegenImplArray.genArray(clazz);
185188
}

src/main/java/com/jsoniter/output/CodegenAccess.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,6 @@ public static void writeVal(String cacheKey, double obj, JsonStream stream) thro
5252
encoder.encodeDouble(obj, stream);
5353
}
5454

55-
public static void writeStringWithoutQuote(JsonStream stream, String val) throws IOException {
56-
StreamImplString.writeString(stream, val);
57-
}
58-
5955
public static void staticGenEncoders(TypeLiteral[] typeLiterals) {
6056
Codegen.staticGenEncoders(typeLiterals);
6157
}

src/main/java/com/jsoniter/output/CodegenContext.java

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/main/java/com/jsoniter/output/CodegenImplArray.java

Lines changed: 32 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,29 @@
55

66
class CodegenImplArray {
77

8-
public static String genArray(Class clazz) {
8+
public static CodegenResult genArray(Class clazz) {
99
Class compType = clazz.getComponentType();
1010
if (compType.isArray()) {
1111
throw new IllegalArgumentException("nested array not supported: " + clazz.getCanonicalName());
1212
}
13-
StringBuilder lines = new StringBuilder();
14-
append(lines, "public static void encode_(java.lang.Object obj, com.jsoniter.output.JsonStream stream) throws java.io.IOException {");
15-
append(lines, "if (obj == null) { stream.writeNull(); return; }");
16-
append(lines, "{{comp}}[] arr = ({{comp}}[])obj;");
17-
append(lines, "if (arr.length == 0) { stream.writeEmptyArray(); return; }");
18-
append(lines, "stream.writeArrayStart();");
19-
append(lines, "int i = 0;");
20-
append(lines, "{{op}}");
21-
append(lines, "while (i < arr.length) {");
22-
append(lines, "stream.writeMore();");
23-
append(lines, "{{op}}");
24-
append(lines, "}");
25-
append(lines, "stream.writeArrayEnd();");
26-
append(lines, "}");
27-
return lines.toString()
28-
.replace("{{comp}}", compType.getCanonicalName())
29-
.replace("{{op}}", CodegenImplNative.genWriteOp("arr[i++]", compType));
13+
CodegenResult ctx = new CodegenResult();
14+
ctx.append("public static void encode_(java.lang.Object obj, com.jsoniter.output.JsonStream stream) throws java.io.IOException {");
15+
ctx.append("if (obj == null) { stream.writeNull(); return; }");
16+
ctx.append(String.format("%s[] arr = (%s[])obj;", compType.getCanonicalName(), compType.getCanonicalName()));
17+
ctx.append("if (arr.length == 0) { return; }");
18+
ctx.buffer('[');
19+
ctx.append("int i = 0;");
20+
CodegenImplNative.genWriteOp(ctx, "arr[i++]", compType);
21+
ctx.append("while (i < arr.length) {");
22+
ctx.buffer(',');
23+
CodegenImplNative.genWriteOp(ctx, "arr[i++]", compType);
24+
ctx.append("}");
25+
ctx.buffer(']');
26+
ctx.append("}");
27+
return ctx;
3028
}
3129

32-
private static void append(StringBuilder lines, String str) {
33-
lines.append(str);
34-
lines.append("\n");
35-
}
36-
37-
public static String genCollection(Class clazz, Type[] typeArgs) {
30+
public static CodegenResult genCollection(Class clazz, Type[] typeArgs) {
3831
Type compType = Object.class;
3932
if (typeArgs.length == 0) {
4033
// default to List<Object>
@@ -53,23 +46,21 @@ public static String genCollection(Class clazz, Type[] typeArgs) {
5346
return genCollection(clazz, compType);
5447
}
5548

56-
private static String genCollection(Class clazz, Type compType) {
57-
StringBuilder lines = new StringBuilder();
58-
append(lines, "public static void encode_(java.lang.Object obj, com.jsoniter.output.JsonStream stream) throws java.io.IOException {");
59-
append(lines, "if (obj == null) { stream.writeNull(); return; }");
60-
append(lines, "java.util.Iterator iter = ((java.util.Collection)obj).iterator();");
61-
append(lines, "if (!iter.hasNext()) { stream.writeEmptyArray(); return; }");
62-
append(lines, "stream.writeArrayStart();");
63-
append(lines, "{{op}}");
64-
append(lines, "while (iter.hasNext()) {");
65-
append(lines, "stream.writeMore();");
66-
append(lines, "{{op}}");
67-
append(lines, "}");
68-
append(lines, "stream.writeArrayEnd();");
69-
append(lines, "}");
70-
return lines.toString()
71-
.replace("{{comp}}", CodegenImplNative.getTypeName(compType))
72-
.replace("{{op}}", CodegenImplNative.genWriteOp("iter.next()", compType));
49+
private static CodegenResult genCollection(Class clazz, Type compType) {
50+
CodegenResult ctx = new CodegenResult();
51+
ctx.append("public static void encode_(java.lang.Object obj, com.jsoniter.output.JsonStream stream) throws java.io.IOException {");
52+
ctx.append("if (obj == null) { stream.writeNull(); return; }");
53+
ctx.append("java.util.Iterator iter = ((java.util.Collection)obj).iterator();");
54+
ctx.append("if (!iter.hasNext()) { return; }");
55+
ctx.buffer('[');
56+
CodegenImplNative.genWriteOp(ctx, "iter.next()", compType);
57+
ctx.append("while (iter.hasNext()) {");
58+
ctx.buffer(',');
59+
CodegenImplNative.genWriteOp(ctx, "iter.next()", compType);
60+
ctx.append("}");
61+
ctx.buffer(']');
62+
ctx.append("}");
63+
return ctx;
7364
}
7465

7566
}

0 commit comments

Comments
 (0)