Skip to content

Commit d84a9f3

Browse files
committed
Resolve conflict with master
2 parents 91093ff + 7ddb55c commit d84a9f3

File tree

6 files changed

+116
-83
lines changed

6 files changed

+116
-83
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,11 @@ private static synchronized Encoder gen(final String cacheKey, Type type) {
7272
try {
7373
EncodingMode mode = JsoniterSpi.getCurrentConfig().encodingMode();
7474
if (mode != EncodingMode.REFLECTION_MODE) {
75+
Type originalType = type;
7576
type = chooseAccessibleSuper(type);
77+
if (Object.class == type) {
78+
throw new JsonException("dynamic code can not serialize private class: " + originalType);
79+
}
7680
}
7781
ClassInfo classInfo = new ClassInfo(type);
7882
if (Map.class.isAssignableFrom(classInfo.clazz) && classInfo.typeArgs.length > 1) {

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

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.jsoniter.output;
22

3-
import com.jsoniter.CodegenAccess;
43
import com.jsoniter.spi.*;
54

65
import java.util.*;
@@ -10,27 +9,13 @@ public static CodegenResult genObject(ClassInfo classInfo) {
109

1110
CodegenResult ctx = new CodegenResult();
1211
ClassDescriptor desc = ClassDescriptor.getEncodingClassDescriptor(classInfo, false);
13-
HashMap<String, Binding> bindings = new HashMap<String, Binding>();
14-
for (Binding binding : desc.allEncoderBindings()) {
15-
for (String toName : binding.toNames) {
16-
bindings.put(toName, binding);
17-
}
18-
}
19-
ArrayList<String> toNames = new ArrayList<String>(bindings.keySet());
20-
Collections.sort(toNames, new Comparator<String>() {
21-
@Override
22-
public int compare(String o1, String o2) {
23-
int x = CodegenAccess.calcHash(o1);
24-
int y = CodegenAccess.calcHash(o2);
25-
return (x < y) ? -1 : ((x == y) ? 0 : 1);
26-
}
27-
});
12+
List<EncodeTo> encodeTos = desc.encodeTos();
2813
ctx.append(String.format("public static void encode_(%s obj, com.jsoniter.output.JsonStream stream) throws java.io.IOException {", classInfo.clazz.getCanonicalName()));
2914
if (hasFieldOutput(desc)) {
3015
int notFirst = 0;
3116
ctx.buffer('{');
32-
for (String toName : toNames) {
33-
notFirst = genField(ctx, bindings.get(toName), toName, notFirst);
17+
for (EncodeTo encodeTo : encodeTos) {
18+
notFirst = genField(ctx, encodeTo.binding, encodeTo.toName, notFirst);
3419
}
3520
for (UnwrapperDescriptor unwrapper : desc.unwrappers) {
3621
if (unwrapper.isMap) {
@@ -62,12 +47,7 @@ private static boolean hasFieldOutput(ClassDescriptor desc) {
6247
if (!desc.unwrappers.isEmpty()) {
6348
return true;
6449
}
65-
for (Binding binding : desc.allEncoderBindings()) {
66-
if (binding.toNames.length > 0) {
67-
return true;
68-
}
69-
}
70-
return false;
50+
return !desc.encodeTos().isEmpty();
7151
}
7252

7353
private static int genField(CodegenResult ctx, Binding binding, String toName, int notFirst) {

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

Lines changed: 44 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,31 @@
44
import com.jsoniter.any.Any;
55

66
import java.io.IOException;
7+
import java.lang.reflect.Field;
8+
import java.util.ArrayList;
79
import java.util.HashMap;
10+
import java.util.List;
811
import java.util.Map;
912

1013
class ReflectionObjectEncoder implements Encoder.ReflectionEncoder {
1114

1215
private final ClassDescriptor desc;
16+
private final List<EncodeTo> fields = new ArrayList<EncodeTo>();
17+
private final List<EncodeTo> getters = new ArrayList<EncodeTo>();
1318

1419
public ReflectionObjectEncoder(ClassInfo classInfo) {
1520
desc = ClassDescriptor.getEncodingClassDescriptor(classInfo, true);
16-
for (Binding binding : desc.allEncoderBindings()) {
21+
for (EncodeTo encodeTo : desc.encodeTos()) {
22+
Binding binding = encodeTo.binding;
1723
if (binding.encoder == null) {
1824
// the field encoder might be registered directly
1925
binding.encoder = JsoniterSpi.getEncoder(binding.encoderCacheKey());
2026
}
27+
if (binding.field != null) {
28+
fields.add(encodeTo);
29+
} else {
30+
getters.add(encodeTo);
31+
}
2132
}
2233
}
2334

@@ -34,17 +45,13 @@ public void encode(Object obj, JsonStream stream) throws IOException {
3445
public Any wrap(Object obj) {
3546
HashMap<String, Object> copied = new HashMap<String, Object>();
3647
try {
37-
for (Binding field : desc.fields) {
38-
Object val = field.field.get(obj);
39-
for (String toName : field.toNames) {
40-
copied.put(toName, val);
41-
}
48+
for (EncodeTo encodeTo : fields) {
49+
Object val = encodeTo.binding.field.get(obj);
50+
copied.put(encodeTo.toName, val);
4251
}
43-
for (Binding getter : desc.getters) {
44-
Object val = getter.method.invoke(obj);
45-
for (String toName : getter.toNames) {
46-
copied.put(toName, val);
47-
}
52+
for (EncodeTo getter : getters) {
53+
Object val = getter.binding.method.invoke(obj);
54+
copied.put(getter.toName, val);
4855
}
4956
} catch (Exception e) {
5057
throw new JsonException(e);
@@ -59,48 +66,13 @@ private void enocde_(Object obj, JsonStream stream) throws Exception {
5966
}
6067
stream.writeObjectStart();
6168
boolean notFirst = false;
62-
boolean omitZero = JsoniterSpi.getCurrentConfig().omitZero();
63-
for (Binding field : desc.fields) {
64-
Object val = field.field.get(obj);
65-
for (String toName : field.toNames) {
66-
if (!(field.shouldOmitNull && val == null)) {
67-
if (omitZero && val instanceof Number && ((Number) val).doubleValue() == 0) {
68-
continue;
69-
}
70-
if (notFirst) {
71-
stream.writeMore();
72-
} else {
73-
notFirst = true;
74-
}
75-
stream.writeObjectField(toName);
76-
if (field.encoder != null) {
77-
field.encoder.encode(val, stream);
78-
} else {
79-
stream.writeVal(val);
80-
}
81-
}
82-
}
69+
for (EncodeTo encodeTo : fields) {
70+
Object val = encodeTo.binding.field.get(obj);
71+
notFirst = writeEncodeTo(stream, notFirst, encodeTo, val);
8372
}
84-
for (Binding getter : desc.getters) {
85-
Object val = getter.method.invoke(obj);
86-
for (String toName : getter.toNames) {
87-
if (!(getter.shouldOmitNull && val == null)) {
88-
if (omitZero && val instanceof Number && ((Number) val).doubleValue() == 0) {
89-
continue;
90-
}
91-
if (notFirst) {
92-
stream.writeMore();
93-
} else {
94-
notFirst = true;
95-
}
96-
stream.writeObjectField(toName);
97-
if (getter.encoder != null) {
98-
getter.encoder.encode(val, stream);
99-
} else {
100-
stream.writeVal(val);
101-
}
102-
}
103-
}
73+
for (EncodeTo encodeTo : getters) {
74+
Object val = encodeTo.binding.method.invoke(obj);
75+
notFirst = writeEncodeTo(stream, notFirst, encodeTo, val);
10476
}
10577
for (UnwrapperDescriptor unwrapper : desc.unwrappers) {
10678
if (unwrapper.isMap) {
@@ -125,4 +97,24 @@ private void enocde_(Object obj, JsonStream stream) throws Exception {
12597
}
12698
stream.writeObjectEnd();
12799
}
100+
101+
private boolean writeEncodeTo(JsonStream stream, boolean notFirst, EncodeTo encodeTo, Object val) throws IOException {
102+
if (!(encodeTo.binding.shouldOmitNull && val == null)) {
103+
if (JsoniterSpi.getCurrentConfig().omitZero() && val instanceof Number && ((Number) val).doubleValue() == 0) {
104+
return notFirst;
105+
}
106+
if (notFirst) {
107+
stream.writeMore();
108+
} else {
109+
notFirst = true;
110+
}
111+
stream.writeObjectField(encodeTo.toName);
112+
if (encodeTo.binding.encoder != null) {
113+
encodeTo.binding.encoder.encode(val, stream);
114+
} else {
115+
stream.writeVal(val);
116+
}
117+
}
118+
return notFirst;
119+
}
128120
}

src/main/java/com/jsoniter/spi/ClassDescriptor.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ public static ClassDescriptor getEncodingClassDescriptor(ClassInfo classInfo, bo
107107
if (binding.encoder != null) {
108108
JsoniterSpi.addNewEncoder(binding.encoderCacheKey(), binding.encoder);
109109
}
110+
if (!binding.isNullable) {
111+
binding.shouldOmitNull = false;
112+
}
110113
}
111114
return desc;
112115
}
@@ -423,10 +426,40 @@ public List<Binding> allDecoderBindings() {
423426
return bindings;
424427
}
425428

429+
426430
public List<Binding> allEncoderBindings() {
427431
ArrayList<Binding> bindings = new ArrayList<Binding>(8);
428432
bindings.addAll(fields);
429433
bindings.addAll(getters);
430434
return bindings;
431435
}
436+
437+
public List<EncodeTo> encodeTos() {
438+
HashMap<String, Integer> previousAppearance = new HashMap<String, Integer>();
439+
ArrayList<EncodeTo> encodeTos = new ArrayList<EncodeTo>(8);
440+
collectEncodeTo(encodeTos, fields, previousAppearance);
441+
collectEncodeTo(encodeTos, getters, previousAppearance);
442+
ArrayList<EncodeTo> removedNulls = new ArrayList<EncodeTo>(encodeTos.size());
443+
for (EncodeTo encodeTo : encodeTos) {
444+
if (encodeTo != null) {
445+
removedNulls.add(encodeTo);
446+
}
447+
}
448+
return removedNulls;
449+
}
450+
451+
private void collectEncodeTo(ArrayList<EncodeTo> encodeTos, List<Binding> fields, HashMap<String, Integer> previousAppearance) {
452+
for (Binding field : fields) {
453+
for (String toName : field.toNames) {
454+
if (previousAppearance.containsKey(toName)) {
455+
encodeTos.set(previousAppearance.get(toName), null);
456+
}
457+
previousAppearance.put(toName, encodeTos.size());
458+
EncodeTo encodeTo = new EncodeTo();
459+
encodeTo.binding = field;
460+
encodeTo.toName = toName;
461+
encodeTos.add(encodeTo);
462+
}
463+
}
464+
}
432465
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.jsoniter.spi;
2+
3+
public class EncodeTo {
4+
public Binding binding;
5+
public String toName;
6+
}

src/test/java/com/jsoniter/output/TestObject.java

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import com.jsoniter.annotation.JsonIgnore;
44
import com.jsoniter.annotation.JsonProperty;
55
import com.jsoniter.spi.Config;
6+
import com.jsoniter.spi.JsonException;
7+
import com.jsoniter.spi.JsoniterSpi;
68
import com.jsoniter.spi.TypeLiteral;
79
import junit.framework.TestCase;
810

@@ -218,21 +220,21 @@ public void test_not_omit_null() {
218220
public static class TestObject11 {
219221
public String field1;
220222
public String field2;
221-
public String field3;
223+
@JsonProperty(nullable = false)
224+
public Integer field3;
222225
}
223226

224227
public void test_omit_null() {
225-
// JsonStream.setMode(EncodingMode.DYNAMIC_MODE);
226-
assertEquals("{}", JsonStream.serialize(new TestObject11()));
228+
assertEquals("{\"field3\":null}", JsonStream.serialize(new TestObject11()));
227229
TestObject11 obj = new TestObject11();
228230
obj.field1 = "hello";
229-
assertEquals("{\"field1\":\"hello\"}", JsonStream.serialize(obj));
231+
assertEquals("{\"field1\":\"hello\",\"field3\":null}", JsonStream.serialize(obj));
230232
obj = new TestObject11();
231233
obj.field2 = "hello";
232-
assertEquals("{\"field2\":\"hello\"}", JsonStream.serialize(obj));
234+
assertEquals("{\"field2\":\"hello\",\"field3\":null}", JsonStream.serialize(obj));
233235
obj = new TestObject11();
234-
obj.field3 = "hello";
235-
assertEquals("{\"field3\":\"hello\"}", JsonStream.serialize(obj));
236+
obj.field3 = 3;
237+
assertEquals("{\"field3\":3}", JsonStream.serialize(obj));
236238
}
237239

238240

@@ -250,4 +252,20 @@ public void test_name_conflict() throws IOException {
250252
stream.close();
251253
assertEquals("{\"field1\":0}", baos.toString());
252254
}
255+
256+
private static class TestObject13 {
257+
}
258+
259+
public void test_private_class() {
260+
EncodingMode encodingMode = JsoniterSpi.getCurrentConfig().encodingMode();
261+
if (EncodingMode.REFLECTION_MODE.equals(encodingMode)) {
262+
return;
263+
}
264+
try {
265+
JsonStream.serialize(new TestObject13());
266+
fail("should throw JsonException");
267+
} catch (JsonException e) {
268+
269+
}
270+
}
253271
}

0 commit comments

Comments
 (0)