Skip to content

Commit 2cf06d2

Browse files
authored
Merge pull request #422 from msgpack/msgpack-jackson-serde-str-as-num
Msgpack jackson serde str as num
2 parents 8637e07 + 31f4cef commit 2cf06d2

File tree

3 files changed

+259
-1
lines changed

3 files changed

+259
-1
lines changed

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

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,42 @@ public void writeNumber(BigDecimal dec)
438438
public void writeNumber(String encodedValue)
439439
throws IOException, JsonGenerationException, UnsupportedOperationException
440440
{
441-
throw new UnsupportedOperationException("writeNumber(String encodedValue) isn't supported yet");
441+
// There is a room to improve this API's performance while the implementation is robust.
442+
// If users can use other MessagePackGenerator#writeNumber APIs that accept
443+
// proper numeric types not String, it's better to use the other APIs instead.
444+
try {
445+
long l = Long.parseLong(encodedValue);
446+
addValueToStackTop(l);
447+
return;
448+
}
449+
catch (NumberFormatException e) {
450+
}
451+
452+
try {
453+
double d = Double.parseDouble(encodedValue);
454+
addValueToStackTop(d);
455+
return;
456+
}
457+
catch (NumberFormatException e) {
458+
}
459+
460+
try {
461+
BigInteger bi = new BigInteger(encodedValue);
462+
addValueToStackTop(bi);
463+
return;
464+
}
465+
catch (NumberFormatException e) {
466+
}
467+
468+
try {
469+
BigDecimal bc = new BigDecimal(encodedValue);
470+
addValueToStackTop(bc);
471+
return;
472+
}
473+
catch (NumberFormatException e) {
474+
}
475+
476+
throw new NumberFormatException(encodedValue);
442477
}
443478

444479
@Override

msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@
1717

1818
import com.fasterxml.jackson.core.JsonGenerator;
1919
import com.fasterxml.jackson.core.JsonEncoding;
20+
import com.fasterxml.jackson.core.JsonProcessingException;
21+
import com.fasterxml.jackson.databind.JsonSerializer;
2022
import com.fasterxml.jackson.databind.ObjectMapper;
23+
import com.fasterxml.jackson.databind.SerializerProvider;
2124
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
25+
import com.fasterxml.jackson.databind.module.SimpleModule;
2226
import org.junit.Test;
2327
import org.msgpack.core.ExtensionTypeHeader;
2428
import org.msgpack.core.MessagePack;
@@ -732,4 +736,152 @@ public void testComplexTypeKeyWithV06Format()
732736
assertThat(unpacker.unpackString(), is("foo"));
733737
assertThat(unpacker.unpackInt(), is(42));
734738
}
739+
740+
// Test serializers that store a string as a number
741+
742+
public static class IntegerSerializerStoringAsString
743+
extends JsonSerializer<Integer>
744+
{
745+
@Override
746+
public void serialize(Integer value, JsonGenerator gen, SerializerProvider serializers)
747+
throws IOException, JsonProcessingException
748+
{
749+
gen.writeNumber(String.valueOf(value));
750+
}
751+
}
752+
753+
@Test
754+
public void serializeStringAsInteger()
755+
throws IOException
756+
{
757+
ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
758+
objectMapper.registerModule(
759+
new SimpleModule().addSerializer(Integer.class, new IntegerSerializerStoringAsString()));
760+
761+
assertThat(
762+
MessagePack.newDefaultUnpacker(objectMapper.writeValueAsBytes(Integer.MAX_VALUE)).unpackInt(),
763+
is(Integer.MAX_VALUE));
764+
}
765+
766+
public static class LongSerializerStoringAsString
767+
extends JsonSerializer<Long>
768+
{
769+
@Override
770+
public void serialize(Long value, JsonGenerator gen, SerializerProvider serializers)
771+
throws IOException, JsonProcessingException
772+
{
773+
gen.writeNumber(String.valueOf(value));
774+
}
775+
}
776+
777+
@Test
778+
public void serializeStringAsLong()
779+
throws IOException
780+
{
781+
ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
782+
objectMapper.registerModule(
783+
new SimpleModule().addSerializer(Long.class, new LongSerializerStoringAsString()));
784+
785+
assertThat(
786+
MessagePack.newDefaultUnpacker(objectMapper.writeValueAsBytes(Long.MIN_VALUE)).unpackLong(),
787+
is(Long.MIN_VALUE));
788+
}
789+
790+
public static class FloatSerializerStoringAsString
791+
extends JsonSerializer<Float>
792+
{
793+
@Override
794+
public void serialize(Float value, JsonGenerator gen, SerializerProvider serializers)
795+
throws IOException, JsonProcessingException
796+
{
797+
gen.writeNumber(String.valueOf(value));
798+
}
799+
}
800+
801+
@Test
802+
public void serializeStringAsFloat()
803+
throws IOException
804+
{
805+
ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
806+
objectMapper.registerModule(
807+
new SimpleModule().addSerializer(Float.class, new FloatSerializerStoringAsString()));
808+
809+
assertThat(
810+
MessagePack.newDefaultUnpacker(objectMapper.writeValueAsBytes(Float.MAX_VALUE)).unpackFloat(),
811+
is(Float.MAX_VALUE));
812+
}
813+
814+
public static class DoubleSerializerStoringAsString
815+
extends JsonSerializer<Double>
816+
{
817+
@Override
818+
public void serialize(Double value, JsonGenerator gen, SerializerProvider serializers)
819+
throws IOException, JsonProcessingException
820+
{
821+
gen.writeNumber(String.valueOf(value));
822+
}
823+
}
824+
825+
@Test
826+
public void serializeStringAsDouble()
827+
throws IOException
828+
{
829+
ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
830+
objectMapper.registerModule(
831+
new SimpleModule().addSerializer(Double.class, new DoubleSerializerStoringAsString()));
832+
833+
assertThat(
834+
MessagePack.newDefaultUnpacker(objectMapper.writeValueAsBytes(Double.MIN_VALUE)).unpackDouble(),
835+
is(Double.MIN_VALUE));
836+
}
837+
838+
public static class BigDecimalSerializerStoringAsString
839+
extends JsonSerializer<BigDecimal>
840+
{
841+
@Override
842+
public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers)
843+
throws IOException, JsonProcessingException
844+
{
845+
gen.writeNumber(String.valueOf(value));
846+
}
847+
}
848+
849+
@Test
850+
public void serializeStringAsBigDecimal()
851+
throws IOException
852+
{
853+
ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
854+
objectMapper.registerModule(
855+
new SimpleModule().addSerializer(BigDecimal.class, new BigDecimalSerializerStoringAsString()));
856+
857+
BigDecimal bd = BigDecimal.valueOf(Long.MAX_VALUE).add(BigDecimal.ONE);
858+
assertThat(
859+
MessagePack.newDefaultUnpacker(objectMapper.writeValueAsBytes(bd)).unpackDouble(),
860+
is(bd.doubleValue()));
861+
}
862+
863+
public static class BigIntegerSerializerStoringAsString
864+
extends JsonSerializer<BigInteger>
865+
{
866+
@Override
867+
public void serialize(BigInteger value, JsonGenerator gen, SerializerProvider serializers)
868+
throws IOException, JsonProcessingException
869+
{
870+
gen.writeNumber(String.valueOf(value));
871+
}
872+
}
873+
874+
@Test
875+
public void serializeStringAsBigInteger()
876+
throws IOException
877+
{
878+
ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
879+
objectMapper.registerModule(
880+
new SimpleModule().addSerializer(BigInteger.class, new BigIntegerSerializerStoringAsString()));
881+
882+
BigInteger bi = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE);
883+
assertThat(
884+
MessagePack.newDefaultUnpacker(objectMapper.writeValueAsBytes(bi)).unpackDouble(),
885+
is(bi.doubleValue()));
886+
}
735887
}

msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,4 +780,75 @@ public void parserShouldReadStrAsBin()
780780
assertEquals("foo", binKeyPojo.s);
781781
assertArrayEquals("bar".getBytes(), binKeyPojo.b);
782782
}
783+
784+
// Test deserializers that parse a string as a number.
785+
// Actually, com.fasterxml.jackson.databind.deser.std.StdDeserializer._parseInteger() takes care of it.
786+
787+
@Test
788+
public void deserializeStringAsInteger()
789+
throws IOException
790+
{
791+
ByteArrayOutputStream out = new ByteArrayOutputStream();
792+
MessagePack.newDefaultPacker(out).packString(String.valueOf(Integer.MAX_VALUE)).close();
793+
794+
Integer v = objectMapper.readValue(out.toByteArray(), Integer.class);
795+
assertThat(v, is(Integer.MAX_VALUE));
796+
}
797+
798+
@Test
799+
public void deserializeStringAsLong()
800+
throws IOException
801+
{
802+
ByteArrayOutputStream out = new ByteArrayOutputStream();
803+
MessagePack.newDefaultPacker(out).packString(String.valueOf(Long.MIN_VALUE)).close();
804+
805+
Long v = objectMapper.readValue(out.toByteArray(), Long.class);
806+
assertThat(v, is(Long.MIN_VALUE));
807+
}
808+
809+
@Test
810+
public void deserializeStringAsFloat()
811+
throws IOException
812+
{
813+
ByteArrayOutputStream out = new ByteArrayOutputStream();
814+
MessagePack.newDefaultPacker(out).packString(String.valueOf(Float.MAX_VALUE)).close();
815+
816+
Float v = objectMapper.readValue(out.toByteArray(), Float.class);
817+
assertThat(v, is(Float.MAX_VALUE));
818+
}
819+
820+
@Test
821+
public void deserializeStringAsDouble()
822+
throws IOException
823+
{
824+
ByteArrayOutputStream out = new ByteArrayOutputStream();
825+
MessagePack.newDefaultPacker(out).packString(String.valueOf(Double.MIN_VALUE)).close();
826+
827+
Double v = objectMapper.readValue(out.toByteArray(), Double.class);
828+
assertThat(v, is(Double.MIN_VALUE));
829+
}
830+
831+
@Test
832+
public void deserializeStringAsBigInteger()
833+
throws IOException
834+
{
835+
ByteArrayOutputStream out = new ByteArrayOutputStream();
836+
BigInteger bi = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE);
837+
MessagePack.newDefaultPacker(out).packString(bi.toString()).close();
838+
839+
BigInteger v = objectMapper.readValue(out.toByteArray(), BigInteger.class);
840+
assertThat(v, is(bi));
841+
}
842+
843+
@Test
844+
public void deserializeStringAsBigDecimal()
845+
throws IOException
846+
{
847+
ByteArrayOutputStream out = new ByteArrayOutputStream();
848+
BigDecimal bd = BigDecimal.valueOf(Double.MAX_VALUE);
849+
MessagePack.newDefaultPacker(out).packString(bd.toString()).close();
850+
851+
BigDecimal v = objectMapper.readValue(out.toByteArray(), BigDecimal.class);
852+
assertThat(v, is(bd));
853+
}
783854
}

0 commit comments

Comments
 (0)