Skip to content

Commit 1cbd05f

Browse files
authored
Add support for jackson field ids (#868)
* Add test demonstrating field id case * Fix java 8 error * Add missing import * Add missing throws * Cleanup unused imports * Cleanup test * Implement jackson field ids * Address feedback from @komamitsu * Address feedback from @komamitsu * Address feedback from @komamitsu
1 parent f480b7b commit 1cbd05f

File tree

4 files changed

+164
-4
lines changed

4 files changed

+164
-4
lines changed

msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public class MessagePackFactory
3939
private final MessagePack.PackerConfig packerConfig;
4040
private boolean reuseResourceInGenerator = true;
4141
private boolean reuseResourceInParser = true;
42+
private boolean supportIntegerKeys = false;
4243
private ExtensionTypeCustomDeserializers extTypeCustomDesers;
4344

4445
public MessagePackFactory()
@@ -74,6 +75,12 @@ public MessagePackFactory setReuseResourceInParser(boolean reuseResourceInParser
7475
return this;
7576
}
7677

78+
public MessagePackFactory setSupportIntegerKeys(boolean supportIntegerKeys)
79+
{
80+
this.supportIntegerKeys = supportIntegerKeys;
81+
return this;
82+
}
83+
7784
public MessagePackFactory setExtTypeCustomDesers(ExtensionTypeCustomDeserializers extTypeCustomDesers)
7885
{
7986
this.extTypeCustomDesers = extTypeCustomDesers;
@@ -84,7 +91,7 @@ public MessagePackFactory setExtTypeCustomDesers(ExtensionTypeCustomDeserializer
8491
public JsonGenerator createGenerator(OutputStream out, JsonEncoding enc)
8592
throws IOException
8693
{
87-
return new MessagePackGenerator(_generatorFeatures, _objectCodec, out, packerConfig, reuseResourceInGenerator);
94+
return new MessagePackGenerator(_generatorFeatures, _objectCodec, out, packerConfig, reuseResourceInGenerator, supportIntegerKeys);
8895
}
8996

9097
@Override

msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ public class MessagePackGenerator
5050
private static final ThreadLocal<OutputStreamBufferOutput> messageBufferOutputHolder = new ThreadLocal<>();
5151
private final OutputStream output;
5252
private final MessagePack.PackerConfig packerConfig;
53+
private final boolean supportIntegerKeys;
5354

5455
private int currentParentElementIndex = -1;
5556
private int currentState = IN_ROOT;
@@ -188,28 +189,32 @@ private MessagePackGenerator(
188189
int features,
189190
ObjectCodec codec,
190191
OutputStream out,
191-
MessagePack.PackerConfig packerConfig)
192+
MessagePack.PackerConfig packerConfig,
193+
boolean supportIntegerKeys)
192194
{
193195
super(features, codec);
194196
this.output = out;
195197
this.messagePacker = packerConfig.newPacker(out);
196198
this.packerConfig = packerConfig;
197199
this.nodes = new ArrayList<>();
200+
this.supportIntegerKeys = supportIntegerKeys;
198201
}
199202

200203
public MessagePackGenerator(
201204
int features,
202205
ObjectCodec codec,
203206
OutputStream out,
204207
MessagePack.PackerConfig packerConfig,
205-
boolean reuseResourceInGenerator)
208+
boolean reuseResourceInGenerator,
209+
boolean supportIntegerKeys)
206210
throws IOException
207211
{
208212
super(features, codec);
209213
this.output = out;
210214
this.messagePacker = packerConfig.newPacker(getMessageBufferOutputForOutputStream(out, reuseResourceInGenerator));
211215
this.packerConfig = packerConfig;
212216
this.nodes = new ArrayList<>();
217+
this.supportIntegerKeys = supportIntegerKeys;
213218
}
214219

215220
private MessageBufferOutput getMessageBufferOutputForOutputStream(
@@ -373,7 +378,7 @@ else if (v instanceof MessagePackExtensionType) {
373378
else {
374379
messagePacker.flush();
375380
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
376-
MessagePackGenerator messagePackGenerator = new MessagePackGenerator(getFeatureMask(), getCodec(), outputStream, packerConfig);
381+
MessagePackGenerator messagePackGenerator = new MessagePackGenerator(getFeatureMask(), getCodec(), outputStream, packerConfig, supportIntegerKeys);
377382
getCodec().writeValue(messagePackGenerator, v);
378383
output.write(outputStream.toByteArray());
379384
}
@@ -513,6 +518,17 @@ private void writeByteArrayTextKey(byte[] text, int offset, int len) throws IOEx
513518
addValueNode(new String(text, offset, len, DEFAULT_CHARSET));
514519
}
515520

521+
@Override
522+
public void writeFieldId(long id) throws IOException
523+
{
524+
if (this.supportIntegerKeys) {
525+
addKeyNode(id);
526+
}
527+
else {
528+
super.writeFieldId(id);
529+
}
530+
}
531+
516532
@Override
517533
public void writeFieldName(String name)
518534
{

msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,11 @@ public String currentName()
621621
return streamReadContext.getCurrentName();
622622
}
623623

624+
public boolean isCurrentFieldId()
625+
{
626+
return this.type == Type.INT || this.type == Type.LONG;
627+
}
628+
624629
@Override
625630
public String getCurrentName()
626631
throws IOException
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
//
2+
// MessagePack for Java
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
package org.msgpack.jackson.dataformat;
17+
18+
import com.fasterxml.jackson.core.JsonParser;
19+
import com.fasterxml.jackson.core.type.TypeReference;
20+
import com.fasterxml.jackson.databind.DeserializationContext;
21+
import com.fasterxml.jackson.databind.JsonDeserializer;
22+
import com.fasterxml.jackson.databind.KeyDeserializer;
23+
import com.fasterxml.jackson.databind.ObjectMapper;
24+
import com.fasterxml.jackson.databind.deser.NullValueProvider;
25+
import com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators;
26+
import com.fasterxml.jackson.databind.deser.std.MapDeserializer;
27+
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
28+
import com.fasterxml.jackson.databind.module.SimpleModule;
29+
import com.fasterxml.jackson.databind.type.TypeFactory;
30+
31+
import java.io.IOException;
32+
import java.util.HashMap;
33+
import java.util.Map;
34+
import java.util.Set;
35+
import java.util.LinkedHashMap;
36+
import org.junit.Test;
37+
38+
import static org.junit.Assert.assertEquals;
39+
40+
public class MessagePackDataformatForFieldIdTest
41+
{
42+
static class MessagePackMapDeserializer extends MapDeserializer
43+
{
44+
public static KeyDeserializer keyDeserializer = new KeyDeserializer()
45+
{
46+
@Override
47+
public Object deserializeKey(String s, DeserializationContext deserializationContext)
48+
throws IOException
49+
{
50+
JsonParser parser = deserializationContext.getParser();
51+
if (parser instanceof MessagePackParser) {
52+
MessagePackParser p = (MessagePackParser) parser;
53+
if (p.isCurrentFieldId()) {
54+
return Integer.valueOf(s);
55+
}
56+
}
57+
return s;
58+
}
59+
};
60+
61+
public MessagePackMapDeserializer()
62+
{
63+
super(
64+
TypeFactory.defaultInstance().constructMapType(Map.class, Object.class, Object.class),
65+
JDKValueInstantiators.findStdValueInstantiator(null, LinkedHashMap.class),
66+
keyDeserializer, null, null);
67+
}
68+
69+
public MessagePackMapDeserializer(MapDeserializer src, KeyDeserializer keyDeser,
70+
JsonDeserializer<Object> valueDeser, TypeDeserializer valueTypeDeser, NullValueProvider nuller,
71+
Set<String> ignorable, Set<String> includable)
72+
{
73+
super(src, keyDeser, valueDeser, valueTypeDeser, nuller, ignorable, includable);
74+
}
75+
76+
@Override
77+
protected MapDeserializer withResolved(KeyDeserializer keyDeser, TypeDeserializer valueTypeDeser,
78+
JsonDeserializer<?> valueDeser, NullValueProvider nuller, Set<String> ignorable,
79+
Set<String> includable)
80+
{
81+
return new MessagePackMapDeserializer(this, keyDeser, (JsonDeserializer<Object>) valueDeser, valueTypeDeser,
82+
nuller, ignorable, includable);
83+
}
84+
}
85+
86+
@Test
87+
public void testMixedKeys()
88+
throws IOException
89+
{
90+
ObjectMapper mapper = new ObjectMapper(
91+
new MessagePackFactory()
92+
.setSupportIntegerKeys(true)
93+
)
94+
.registerModule(new SimpleModule()
95+
.addDeserializer(Map.class, new MessagePackMapDeserializer()));
96+
97+
Map<Object, Object> map = new HashMap<>();
98+
map.put(1, "one");
99+
map.put("2", "two");
100+
101+
byte[] bytes = mapper.writeValueAsBytes(map);
102+
Map<Object, Object> deserializedInit = mapper.readValue(bytes, new TypeReference<Map<Object, Object>>() {});
103+
104+
Map<Object, Object> expected = new HashMap<>(map);
105+
Map<Object, Object> actual = new HashMap<>(deserializedInit);
106+
107+
assertEquals(expected, actual);
108+
}
109+
110+
@Test
111+
public void testMixedKeysBackwardsCompatiable()
112+
throws IOException
113+
{
114+
ObjectMapper mapper = new ObjectMapper(new MessagePackFactory())
115+
.registerModule(new SimpleModule()
116+
.addDeserializer(Map.class, new MessagePackMapDeserializer()));
117+
118+
Map<Object, Object> map = new HashMap<>();
119+
map.put(1, "one");
120+
map.put("2", "two");
121+
122+
byte[] bytes = mapper.writeValueAsBytes(map);
123+
Map<Object, Object> deserializedInit = mapper.readValue(bytes, new TypeReference<Map<Object, Object>>() {});
124+
125+
Map<Object, Object> expected = new HashMap<>();
126+
expected.put("1", "one");
127+
expected.put("2", "two");
128+
Map<Object, Object> actual = new HashMap<>(deserializedInit);
129+
130+
assertEquals(expected, actual);
131+
}
132+
}

0 commit comments

Comments
 (0)