Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Serialization of custom Map implementations using dynamic codegen mode is broken (tested on latest: 0.9.22) #189

Copy link
Copy link
@adiosmsu

Description

@adiosmsu
Issue body actions

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.

Reactions are currently unavailable

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.