Skip to content

Commit 05d397c

Browse files
committed
support number key
1 parent 21a4ad8 commit 05d397c

File tree

9 files changed

+85
-59
lines changed

9 files changed

+85
-59
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ private static synchronized Encoder gen(final String cacheKey, Type type) {
7979
}
8080
ClassInfo classInfo = new ClassInfo(type);
8181
if (Map.class.isAssignableFrom(classInfo.clazz) && classInfo.typeArgs.length > 1) {
82-
DefaultMapKeyEncoder.registerOrGetExisting(classInfo.typeArgs[0]);
82+
MapKeyEncoders.registerOrGetExisting(classInfo.typeArgs[0]);
8383
}
8484
if (mode == EncodingMode.REFLECTION_MODE) {
8585
encoder = ReflectionEncoderFactory.create(classInfo);

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ public static void writeVal(String cacheKey, double obj, JsonStream stream) thro
5353
}
5454

5555
public static void writeMapKey(String cacheKey, Object mapKey, JsonStream stream) throws IOException {
56-
String encodedMapKey = JsoniterSpi.getMapKeyEncoder(cacheKey).encode(mapKey);
57-
stream.writeVal(encodedMapKey);
56+
Encoder mapKeyEncoder = JsoniterSpi.getMapKeyEncoder(cacheKey);
57+
mapKeyEncoder.encode(mapKey, stream);
5858
}
5959

6060
public static void writeStringWithoutQuote(String obj, JsonStream stream) throws IOException {

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

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

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,15 @@ public final void writeObjectField(String field) throws IOException {
331331
}
332332
}
333333

334+
public final void writeObjectField(Object key, Encoder keyEncoder) throws IOException {
335+
keyEncoder.encode(key, this);
336+
if (indention > 0) {
337+
write((byte) ':', (byte) ' ');
338+
} else {
339+
write(':');
340+
}
341+
}
342+
334343
public final void writeObjectEnd() throws IOException {
335344
int indentionStep = currentConfig().indentionStep();
336345
writeIndention(indentionStep);
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.jsoniter.output;
2+
3+
import com.jsoniter.spi.*;
4+
5+
import java.io.IOException;
6+
import java.lang.reflect.Type;
7+
8+
class MapKeyEncoders {
9+
10+
public static Encoder registerOrGetExisting(Type mapKeyType) {
11+
String cacheKey = JsoniterSpi.getMapKeyEncoderCacheKey(mapKeyType);
12+
Encoder mapKeyEncoder = JsoniterSpi.getMapKeyEncoder(cacheKey);
13+
if (null != mapKeyEncoder) {
14+
return mapKeyEncoder;
15+
}
16+
mapKeyEncoder = createDefaultEncoder(mapKeyType);
17+
JsoniterSpi.addNewMapEncoder(cacheKey, mapKeyEncoder);
18+
return mapKeyEncoder;
19+
}
20+
21+
private static Encoder createDefaultEncoder(Type mapKeyType) {
22+
if (mapKeyType == String.class) {
23+
return new StringKeyEncoder();
24+
}
25+
if (mapKeyType instanceof Class) {
26+
if (Number.class.isAssignableFrom((Class<?>) mapKeyType)) {
27+
return new NumberKeyEncoder();
28+
}
29+
}
30+
throw new JsonException("can not encode map key type: " + mapKeyType);
31+
}
32+
33+
private static class StringKeyEncoder implements Encoder {
34+
35+
@Override
36+
public void encode(Object obj, JsonStream stream) throws IOException {
37+
stream.writeVal(obj);
38+
}
39+
}
40+
41+
private static class NumberKeyEncoder implements Encoder {
42+
43+
@Override
44+
public void encode(Object obj, JsonStream stream) throws IOException {
45+
stream.write('"');
46+
stream.writeVal(obj);
47+
stream.write('"');
48+
}
49+
}
50+
}

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

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
class ReflectionMapEncoder implements Encoder.ReflectionEncoder {
1212

1313
private final TypeLiteral valueTypeLiteral;
14-
private final MapKeyEncoder mapKeyEncoder;
14+
private final Encoder mapKeyEncoder;
1515

1616
public ReflectionMapEncoder(Class clazz, Type[] typeArgs) {
1717
Type keyType = String.class;
@@ -20,11 +20,7 @@ public ReflectionMapEncoder(Class clazz, Type[] typeArgs) {
2020
keyType = typeArgs[0];
2121
valueType = typeArgs[1];
2222
}
23-
if (keyType == String.class) {
24-
mapKeyEncoder = null;
25-
} else {
26-
mapKeyEncoder = DefaultMapKeyEncoder.registerOrGetExisting(keyType);
27-
}
23+
mapKeyEncoder = MapKeyEncoders.registerOrGetExisting(keyType);
2824
valueTypeLiteral = TypeLiteral.create(valueType);
2925
}
3026

@@ -58,11 +54,7 @@ private boolean writeEntry(JsonStream stream, boolean notFirst, Map.Entry<Object
5854
stream.writeIndention();
5955
notFirst = true;
6056
}
61-
if (mapKeyEncoder == null) {
62-
stream.writeObjectField((String) entry.getKey());
63-
} else {
64-
stream.writeObjectField(mapKeyEncoder.encode(entry.getKey()));
65-
}
57+
stream.writeObjectField(entry.getKey(), mapKeyEncoder);
6658
stream.writeVal(valueTypeLiteral, entry.getValue());
6759
return notFirst;
6860
}

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public class JsoniterSpi {
1313
private static List<Extension> extensions = new ArrayList<Extension>();
1414
private static Map<Class, Class> typeImpls = new HashMap<Class, Class>();
1515
private static Map<Type, MapKeyDecoder> globalMapKeyDecoders = new HashMap<Type, MapKeyDecoder>();
16-
private static Map<Type, MapKeyEncoder> globalMapKeyEncoders = new HashMap<Type, MapKeyEncoder>();
16+
private static Map<Type, Encoder> globalMapKeyEncoders = new HashMap<Type, Encoder>();
1717
private static Map<Type, Decoder> globalTypeDecoders = new HashMap<Type, Decoder>();
1818
private static Map<Type, Encoder> globalTypeEncoders = new HashMap<Type, Encoder>();
1919
private static Map<TypeProperty, Decoder> globalPropertyDecoders = new HashMap<TypeProperty, Decoder>();
@@ -27,7 +27,7 @@ protected Config initialValue() {
2727
}
2828
};
2929
private static volatile Map<Object, String> configNames = new HashMap<Object, String>();
30-
private static volatile Map<String, MapKeyEncoder> mapKeyEncoders = new HashMap<String, MapKeyEncoder>();
30+
private static volatile Map<String, Encoder> mapKeyEncoders = new HashMap<String, Encoder>();
3131
private static volatile Map<String, MapKeyDecoder> mapKeyDecoders = new HashMap<String, MapKeyDecoder>();
3232
private static volatile Map<String, Encoder> encoders = new HashMap<String, Encoder>();
3333
private static volatile Map<String, Decoder> decoders = new HashMap<String, Decoder>();
@@ -103,7 +103,7 @@ public static void registerMapKeyDecoder(Type mapKeyType, MapKeyDecoder mapKeyDe
103103
copyGlobalMapKeyDecoder(getCurrentConfig().configName(), mapKeyType, mapKeyDecoder);
104104
}
105105

106-
public static void registerMapKeyEncoder(Type mapKeyType, MapKeyEncoder mapKeyEncoder) {
106+
public static void registerMapKeyEncoder(Type mapKeyType, Encoder mapKeyEncoder) {
107107
globalMapKeyEncoders.put(mapKeyType, mapKeyEncoder);
108108
copyGlobalMapKeyEncoder(getCurrentConfig().configName(), mapKeyType, mapKeyEncoder);
109109
}
@@ -162,7 +162,7 @@ private static void copyGlobalSettings(String configName) {
162162
for (Map.Entry<Type, MapKeyDecoder> entry : globalMapKeyDecoders.entrySet()) {
163163
copyGlobalMapKeyDecoder(configName, entry.getKey(), entry.getValue());
164164
}
165-
for (Map.Entry<Type, MapKeyEncoder> entry : globalMapKeyEncoders.entrySet()) {
165+
for (Map.Entry<Type, Encoder> entry : globalMapKeyEncoders.entrySet()) {
166166
copyGlobalMapKeyEncoder(configName, entry.getKey(), entry.getValue());
167167
}
168168
for (Map.Entry<Type, Decoder> entry : globalTypeDecoders.entrySet()) {
@@ -200,7 +200,7 @@ private static void copyGlobalMapKeyDecoder(String configName, Type mapKeyType,
200200
addNewMapDecoder(TypeLiteral.create(mapKeyType).getDecoderCacheKey(configName), mapKeyDecoder);
201201
}
202202

203-
private static void copyGlobalMapKeyEncoder(String configName, Type mapKeyType, MapKeyEncoder mapKeyEncoder) {
203+
private static void copyGlobalMapKeyEncoder(String configName, Type mapKeyType, Encoder mapKeyEncoder) {
204204
addNewMapEncoder(TypeLiteral.create(mapKeyType).getEncoderCacheKey(configName), mapKeyEncoder);
205205
}
206206

@@ -226,13 +226,13 @@ public static MapKeyDecoder getMapKeyDecoder(String cacheKey) {
226226
return mapKeyDecoders.get(cacheKey);
227227
}
228228

229-
public synchronized static void addNewMapEncoder(String cacheKey, MapKeyEncoder mapKeyEncoder) {
230-
HashMap<String, MapKeyEncoder> newCache = new HashMap<String, MapKeyEncoder>(mapKeyEncoders);
229+
public synchronized static void addNewMapEncoder(String cacheKey, Encoder mapKeyEncoder) {
230+
HashMap<String, Encoder> newCache = new HashMap<String, Encoder>(mapKeyEncoders);
231231
newCache.put(cacheKey, mapKeyEncoder);
232232
mapKeyEncoders = newCache;
233233
}
234234

235-
public static MapKeyEncoder getMapKeyEncoder(String cacheKey) {
235+
public static Encoder getMapKeyEncoder(String cacheKey) {
236236
return mapKeyEncoders.get(cacheKey);
237237
}
238238

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

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

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

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

3-
import com.jsoniter.spi.Config;
4-
import com.jsoniter.spi.JsoniterSpi;
5-
import com.jsoniter.spi.MapKeyEncoder;
6-
import com.jsoniter.spi.TypeLiteral;
3+
import com.jsoniter.spi.*;
74
import junit.framework.TestCase;
85

96
import java.io.ByteArrayOutputStream;
@@ -70,11 +67,11 @@ public static class TestObject1 {
7067
}
7168

7269
public void test_MapKeyCodec() {
73-
JsoniterSpi.registerMapKeyEncoder(TestObject1.class, new MapKeyEncoder() {
70+
JsoniterSpi.registerMapKeyEncoder(TestObject1.class, new Encoder() {
7471
@Override
75-
public String encode(Object mapKey) {
76-
TestObject1 obj = (TestObject1) mapKey;
77-
return String.valueOf(obj.Field);
72+
public void encode(Object obj, JsonStream stream) throws IOException {
73+
TestObject1 mapKey = (TestObject1) obj;
74+
stream.writeVal(String.valueOf(mapKey.Field));
7875
}
7976
});
8077
HashMap<TestObject1, Object> obj = new HashMap<TestObject1, Object>();
@@ -120,4 +117,11 @@ public void test_indention_with_empty_map() {
120117
.build();
121118
assertEquals("{}", JsonStream.serialize(config, new HashMap<String, String>()));
122119
}
120+
121+
public void test_int_as_map_key() {
122+
HashMap<Integer, Integer> m = new HashMap<Integer, Integer>();
123+
m.put(1, 2);
124+
assertEquals("{\"1\":2}", JsonStream.serialize(new TypeLiteral<Map<Integer, Integer>>(){
125+
}, m));
126+
}
123127
}

0 commit comments

Comments
 (0)