从CBOR

时间:2016-05-13 15:43:53

标签: java serialization jackson

如果我将POJO序列化为二进制格式以区分float和double,例如Smile或CBOR,是否有一种使用序列化类型反序列化为Map的简单方法?例如:

import java.io.*;
import java.util.*;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.cbor.CBORFactory;

import static org.junit.Assert.*;
import org.junit.Test;

public class SimpleJacksonTest {
    private float weight;

    public SimpleJacksonTest() {}

    public float getWeight() {
        return weight;
    }

    public void setWeight(float weight) {
        this.weight = weight;
    }

    @Test
    public void TestMapFromCbor() throws IOException {
        ObjectMapper mapper = new ObjectMapper(new CBORFactory());
        SimpleJacksonTest jack = new SimpleJacksonTest();
        jack.setWeight(123.4F);
        mapper.writeValue(new File("jack.cbor"), jack);

        Map<String,Object> jill = mapper.readValue(new File("jack.cbor"), Map.class);
        assertEquals(Double.class, jill.get("weight").getClass());  // I want Float
    }
}

如果我检查jack.cbor,我可以清楚地看到权重字段被序列化为单精度浮点数:

$ od -c -tx1 jack.cbor
0000000  277   f   w   e   i   g   h   t 372   B 366 314 315 377
           bf  66  77  65  69  67  68  74  fa  42  f6  cc  cd  ff

如何让readValue()将类型保留为序列化?

1 个答案:

答案 0 :(得分:0)

我还没有想到CBOR,但这就是我想出的微笑。我将以下内部类添加到SimpleJacksonTest(以及必需的导入):

private class SmileNumberDeserializer extends NumberDeserializer {
    @Override
    public Number deserialize(JsonParser p, DeserializationContext ctxt)
        throws IOException
    {
        if (JsonTokenId.ID_NUMBER_FLOAT == p.getCurrentTokenId()
            && NumberType.FLOAT == p.getNumberType()) {
            return p.getFloatValue();
        }
        return super.deserialize(p, ctxt);
    }
}

然后我将它合并到映射器中,如下所示:

SimpleModule module = new SimpleModule();
module.addDeserializer(Number.class, new SmileNumberDeserializer());
mapper.registerModule(module);

现在以下断言成功:

assertEquals(Float.class, jill.get("weight").getClass());

这完全取决于保留类型的反序列化器,因此getNumberType()返回NumberType.FLOAT。