Description
There is a bug in dynamic code regarding doubling of ':' symbols. How to reproduce:
import com.google.common.collect.ImmutableMap;
import com.jsoniter.output.EncodingMode;
import com.jsoniter.output.JsonStream;
import java.math.BigDecimal;
public class TestCase {
static void main(String[] args) {
JsonStream.setMode(EncodingMode.DYNAMIC_MODE);
final ImmutableMap<String, Object> of =
ImmutableMap.of("destination", "test_destination_value", "amount", new BigDecimal("0.0000101101"), "password", "test_pass");
final String serialized = JsonStream.serialize(of);
System.out.println(serialized);
}
}
(You must have
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
on a classpath for this to compile)
Result yielded:
{"destination":"test_destination_value","amount"::0.0000101101,"password"::"test_pass"}
As you can notice, there are double ':' symbols after the first property. I believe, that is caused by codegen code in com.jsoniter.output.CodegenImplMap. You start with processing the first property with following lines (roughly, I trimmed the code unrelated to this issue):
ctx.append("java.util.Map.Entry entry = (java.util.Map.Entry)iter.next();");
genWriteMapKey(ctx, keyType, noIndention);
CodegenImplNative.genWriteOp(ctx, "entry.getValue()", valueType, false);
So far everything is OK, but then a 'while' cycle comes which messes things up:
ctx.append("while(iter.hasNext()) {");
ctx.append("entry = (java.util.Map.Entry)iter.next();");
genWriteMapKey(ctx, keyType, noIndention);
ctx.append("stream.write(':');"); //<-----THIS IS BAD
CodegenImplNative.genWriteOp(ctx, "entry.getValue()", valueType, false);
Take note of "stream.write(':');". That is a bug because in runtime "genWriteMapKey" calls "JsonStream.writeObjectField(java.lang.Object, com.jsoniter.spi.Encoder)" which looks like:
public final void writeObjectField(Object key, Encoder keyEncoder) throws IOException {
keyEncoder.encode(key, this);
if (indention > 0) {
write((byte) ':', (byte) ' ');
} else {
write(':');
}
}
As you can see it writes another ':' to a stream. Hence, a doubling.
Hope it helps to fix this fast. For a time being we are falling back to reflection mode which works OK.