Skip to content

Commit 0b4b908

Browse files
committed
cache config on JsonIterator
1 parent 5a51fc8 commit 0b4b908

7 files changed

Lines changed: 74 additions & 8 deletions

File tree

src/main/java/com/jsoniter/JsonIterator.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
public class JsonIterator implements Closeable {
1717

18+
public Config configCache;
1819
private static boolean isStreamingEnabled = false;
1920
final static ValueType[] valueTypes = new ValueType[256];
2021
InputStream in;
@@ -305,12 +306,20 @@ public final <T> T read(T existingObject) throws IOException {
305306
try {
306307
this.existingObject = existingObject;
307308
Class<?> clazz = existingObject.getClass();
308-
return (T) Codegen.getDecoder(TypeLiteral.create(clazz).getDecoderCacheKey(), clazz).decode(this);
309+
String cacheKey = currentConfig().getDecoderCacheKey(clazz);
310+
return (T) Codegen.getDecoder(cacheKey, clazz).decode(this);
309311
} catch (ArrayIndexOutOfBoundsException e) {
310312
throw reportError("read", "premature end");
311313
}
312314
}
313315

316+
private Config currentConfig() {
317+
if (configCache == null) {
318+
configCache = JsoniterSpi.getCurrentConfig();
319+
}
320+
return configCache;
321+
}
322+
314323
/**
315324
* try to bind to existing object, returned object might not the same instance
316325
*
@@ -323,15 +332,17 @@ public final <T> T read(T existingObject) throws IOException {
323332
public final <T> T read(TypeLiteral<T> typeLiteral, T existingObject) throws IOException {
324333
try {
325334
this.existingObject = existingObject;
326-
return (T) Codegen.getDecoder(typeLiteral.getDecoderCacheKey(), typeLiteral.getType()).decode(this);
335+
String cacheKey = currentConfig().getDecoderCacheKey(typeLiteral.getType());
336+
return (T) Codegen.getDecoder(cacheKey, typeLiteral.getType()).decode(this);
327337
} catch (ArrayIndexOutOfBoundsException e) {
328338
throw reportError("read", "premature end");
329339
}
330340
}
331341

332342
public final <T> T read(Class<T> clazz) throws IOException {
333343
try {
334-
return (T) Codegen.getDecoder(TypeLiteral.create(clazz).getDecoderCacheKey(), clazz).decode(this);
344+
String cacheKey = currentConfig().getDecoderCacheKey(clazz);
345+
return (T) Codegen.getDecoder(cacheKey, clazz).decode(this);
335346
} catch (ArrayIndexOutOfBoundsException e) {
336347
throw reportError("read", "premature end");
337348
}

src/main/java/com/jsoniter/JsonIteratorPool.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,31 @@
11
package com.jsoniter;
22

3+
import com.jsoniter.spi.Config;
4+
import com.jsoniter.spi.ConfigListener;
5+
import com.jsoniter.spi.JsoniterSpi;
6+
37
public class JsonIteratorPool {
48

59
private static ThreadLocal<JsonIterator> slot1 = new ThreadLocal<JsonIterator>();
610
private static ThreadLocal<JsonIterator> slot2 = new ThreadLocal<JsonIterator>();
711

12+
static {
13+
JsoniterSpi.registerConfigListener(new ConfigListener() {
14+
15+
@Override
16+
public void onCurrentConfigChanged(Config newConfig) {
17+
JsonIterator iter = slot1.get();
18+
if (iter != null) {
19+
iter.configCache = newConfig;
20+
}
21+
iter = slot2.get();
22+
if (iter != null) {
23+
iter.configCache = newConfig;
24+
}
25+
}
26+
});
27+
}
28+
829
public static JsonIterator borrowJsonIterator() {
930
JsonIterator iter = slot1.get();
1031
if (iter != null) {

src/main/java/com/jsoniter/annotation/JsoniterConfig.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,13 @@
55

66
import java.lang.annotation.Annotation;
77
import java.lang.reflect.*;
8-
import java.util.ArrayList;
9-
import java.util.Arrays;
10-
import java.util.List;
8+
import java.util.*;
119

1210
public class JsoniterConfig extends EmptyExtension implements Config {
1311

1412
private final String configName;
1513
private final Builder builder;
14+
private volatile Map<Type, String> decoderCacheKeys = new HashMap<Type, String>();
1615

1716
public JsoniterConfig(Builder builder) {
1817
this.configName = JsoniterSpi.assignConfigName(builder);
@@ -24,6 +23,24 @@ public String configName() {
2423
return configName;
2524
}
2625

26+
@Override
27+
public String getDecoderCacheKey(Type type) {
28+
String cacheKey = decoderCacheKeys.get(type);
29+
if (cacheKey != null) {
30+
return cacheKey;
31+
}
32+
synchronized(this) {
33+
cacheKey = decoderCacheKeys.get(type);
34+
if (cacheKey != null) {
35+
return cacheKey;
36+
}
37+
cacheKey = TypeLiteral.create(type).getDecoderCacheKey(configName);
38+
HashMap<Type, String> newCache = new HashMap<Type, String>(decoderCacheKeys);
39+
newCache.put(type, cacheKey);
40+
return cacheKey;
41+
}
42+
}
43+
2744
protected Builder builder() {
2845
return builder;
2946
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package com.jsoniter.spi;
22

3+
import java.lang.reflect.Type;
4+
35
public interface Config extends Extension {
46
String configName();
7+
String getDecoderCacheKey(Type type);
58
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.jsoniter.spi;
2+
3+
public interface ConfigListener {
4+
void onCurrentConfigChanged(Config newConfig);
5+
}

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package com.jsoniter.spi;
22

3-
import com.jsoniter.JsonIterator;
43
import com.jsoniter.annotation.JsoniterConfig;
5-
import com.jsoniter.output.JsonStream;
64

75
import java.lang.reflect.Type;
86
import java.util.ArrayList;
@@ -14,6 +12,7 @@ public class JsoniterSpi {
1412

1513
// registered at startup, global state
1614
private static Config defaultConfig;
15+
private static List<ConfigListener> configListeners = new ArrayList<ConfigListener>();
1716
private static List<Extension> extensions = new ArrayList<Extension>();
1817
private static Map<Class, Class> typeImpls = new HashMap<Class, Class>();
1918
private static Map<Type, MapKeyDecoder> globalMapKeyDecoders = new HashMap<Type, MapKeyDecoder>();
@@ -46,6 +45,9 @@ protected Config initialValue() {
4645

4746
public static void setCurrentConfig(Config val) {
4847
currentConfig.set(val);
48+
for (ConfigListener configListener : configListeners) {
49+
configListener.onCurrentConfigChanged(val);
50+
}
4951
}
5052

5153
public static void clearCurrentConfig() {
@@ -82,6 +84,10 @@ private synchronized static String assignNewConfigName(Object obj) {
8284
return configName;
8385
}
8486

87+
public static void registerConfigListener(ConfigListener configListener) {
88+
configListeners.add(configListener);
89+
}
90+
8591
public static void registerExtension(Extension extension) {
8692
if (!extensions.contains(extension)) {
8793
extensions.add(extension);

src/test/java/com/jsoniter/TestGson.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ public static class TestObject2 {
2929
}
3030

3131
public void test_Expose() {
32+
// test if the iterator reuse will keep right config cache
33+
JsonIterator.deserialize(new GsonCompatibilityMode.Builder().build(),
34+
"{\"field-1\":\"hello\"}", TestObject2.class);
3235
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
3336
TestObject2 obj = gson.fromJson("{\"field1\":\"hello\"}", TestObject2.class);
3437
assertNull(obj.field1);

0 commit comments

Comments
 (0)