在 Jackson 中使用自定义序列化程序序列化嵌套对象时出现 JsonGenerationException

头脑风暴

这是我要序列化的类。

public class ItemRow<T> {

    private String id;
    private List<T> items;
}

允许有两种变体。ItemRow<String>, ItemRow<ItemRow>. 在后一种情况下,它将被嵌套。

例如:

ItemRow item1 = new ItemRow("abc", Arrays.asList("item1", "item2", "item3"));
String result = mapper.writeValueAsString(item1);
System.out.println(result);

应该给

{
     "abc":["item1","item2","item3"]
}

现在,后一种情况

ItemRow item2 = new ItemRow("cde", Arrays.asList("item4, item5"));
ItemRow item = new ItemRow("combined", Arrays.asList(item1,item2));
result = mapper.writeValueAsString(item);
System.out.println(result);

应该给

{
    "combined": {
        "abc": ["item1", "item2", "item3"],
        "cde": ["item4", "item5"]
    }
}

但是在序列化后者时我得到了异常。第一个按预期工作。所以我相信递归序列化失败了,但我无法找出原因

这是例外

com.fasterxml.jackson.core.JsonGenerationException: Can not start an object, expecting field name (context: Object)

    at com.fasterxml.jackson.core.JsonGenerator._reportError(JsonGenerator.java:1961)
    at com.fasterxml.jackson.core.json.JsonGeneratorImpl._reportCantWriteValueExpectName(JsonGeneratorImpl.java:244)
    at com.fasterxml.jackson.core.json.WriterBasedJsonGenerator._verifyValueWrite(WriterBasedJsonGenerator.java:866)
    at com.fasterxml.jackson.core.json.WriterBasedJsonGenerator.writeStartObject(WriterBasedJsonGenerator.java:279)
    at hello.ItemRowSerializer.serialize(ItemRow.java:58)
    at hello.ItemRowSerializer.serialize(ItemRow.java:42)
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
    at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2655)
    at com.fasterxml.jackson.core.base.GeneratorBase.writeObject(GeneratorBase.java:381)
    at hello.ItemRowSerializer.serialize(ItemRow.java:67)
    at hello.ItemRowSerializer.serialize(ItemRow.java:42)

序列化器实现

class ItemRowSerializer extends JsonSerializer<ItemRow> {

    @Override
    public void serialize(ItemRow itemRow, JsonGenerator jgen, SerializerProvider serializerProvider) throws IOException {

        String id = itemRow.getId();
        List<Object> items = itemRow.getItems();

        if (items.isEmpty()) {
            jgen.writeStartObject();
            jgen.writeFieldName(id);
            jgen.writeStartArray();
            jgen.writeEndArray();
            jgen.writeEndObject();
        }
        else {
            jgen.writeStartObject();
            Object item = items.get(0);
            jgen.writeFieldName(id);
            if (item instanceof  ItemRow){
                for (Object i : items) {
                    //ItemRow temp = (ItemRow) i;
                    //jgen.writeObjectField(temp.getId(), temp);
                    //jgen.writeObjectField(id, i);
                    jgen.writeStartObject();
                    jgen.writeObject(i);
                    jgen.writeEndObject();
                }
            }
            else {
                //jgen.writeFieldName(id);
                jgen.writeStartArray();
                for (Object arg : items) {
                    jgen.writeString(arg.toString());
                }
                jgen.writeEndArray();
            }
        }
        jgen.writeEndObject();
    }
}
布拉克·阿基尔迪兹

您的序列化程序算法不正确。代码在上面。直接反序列化对象时不需要启动对象。我删除了这一步并最小化了代码。

示例测试;

@Test
public void serializeTest() throws JsonProcessingException
{
    ObjectMapper mapper = new ObjectMapper();

    SimpleModule module = new SimpleModule();
    module.addSerializer(ItemRow.class, new ItemRowSerializer());
    mapper.registerModule(module);

    ItemRow item1 = new ItemRow("abc", Arrays.asList("item1", "item2", "item3"));
    String result = mapper.writeValueAsString(item1);
    System.out.println(result);


    ItemRow item2 = new ItemRow("cde", Arrays.asList("item4", "item5"));


    ItemRow item6 = new ItemRow("deeper-1", Arrays.asList("item6", "item7"));
    ItemRow item7 = new ItemRow("deeper-2", Arrays.asList("item6", "item7"));
    ItemRow item8 = new ItemRow("deeper", Arrays.asList(item6, item7));

    ItemRow item3 = new ItemRow("inner-1", Arrays.asList("item6", "item7"));
    ItemRow item4 = new ItemRow("inner-2", Arrays.asList("item6", "item7"));
    ItemRow item5 = new ItemRow("inner", Arrays.asList(item3, item4, item8));




    ItemRow item = new ItemRow("combined", Arrays.asList(item1,item2,item5));
    result = mapper.writeValueAsString(item);
    System.out.println(result);

}

算法;

public class ItemRowSerializer extends JsonSerializer<ItemRow>
{

    @Override
    public void serialize(ItemRow itemRow, JsonGenerator jgen, SerializerProvider serializerProvider) throws IOException
    {
        jgen.writeStartObject();
        writeInnerObject(jgen, itemRow);
        jgen.writeEndObject();
    }


    private void writeStringArr(JsonGenerator jgen, List items) throws IOException
    {
        jgen.writeStartArray();
        for (Object arg : items)
        {
            jgen.writeString(arg.toString());
        }
        jgen.writeEndArray();
    }


    private void writeInnerObject(JsonGenerator jgen, ItemRow row) throws IOException
    {
        jgen.writeFieldName(row.getId());

        if (row.getItems().size() > 0 && row.getItems().get(0) instanceof ItemRow)
        {
            jgen.writeStartObject();
            for (int i = 0; i < row.getItems().size(); i++)
            {
                ItemRow innerRow = (ItemRow) row.getItems().get(i);
                if( innerRow.getItems().size() > 0 && innerRow.getItems().get(0) instanceof ItemRow )
                {
                    writeInnerObject(jgen, innerRow);
                }
                else
                {
                    jgen.writeFieldName(innerRow.getId());
                    writeStringArr(jgen, innerRow.getItems());
                }
            }
            jgen.writeEndObject();
        }
        else
        {
            writeStringArr(jgen, row.getItems());
        }
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Jackson 不会使用自定义序列化程序序列化 null

JSON Jackson-使用自定义序列化程序序列化多态类时的异常

使用值对象作为实体ID时自定义Jackson序列化

Jackson对多态对象的自定义反序列化

用于Optional <?>的Jackson自定义序列化程序

使用Jackson序列化自定义地图

使用Jackson自定义JSON反序列化

使用Jackson自定义Collection <T>的序列化

使用Jackson自定义反序列化列表

使用Jackson的自定义JSON序列化/反序列化

使用Jackson在Java中嵌套自定义反序列化

在Java中使用Jackson进行JSON FIELD的自定义反序列化?

如何在Jackson上使用自定义序列化程序?

如何对Map <String,Object>使用Jackson自定义值序列化程序?

在Java中使用Jackson反序列化Date字段时引发自定义异常

某些字段的Jackson JSON自定义序列化

自定义序列化器和Jackson模式

使用Jackson进行自定义反序列化:扩展默认反序列化器

使用Jackson序列化带有嵌套对象的POJO

Jackson 的多态序列化/反序列化和自定义序列化器/反序列化器

Jackson-自定义序列化程序,仅覆盖特定字段

带有注释的类的Jackson自定义序列化程序

当值为“ null”时,Jackson忽略自定义字段反序列化器

使用自定义反序列化器 Jackson 将 .json 文件转换为 Java 对象

仅当存在某些字段时才使用自定义JSON反序列化(使用Jackson)

使用jackson-dataformat-xml自定义根元素的XML反序列化?

使用Jackson自定义反序列化JSON字段

Jackson JSON无法使用自定义根名称反序列化元素数组?

Jersey + Jackson JSON日期格式序列化-如何更改格式或使用自定义JacksonJsonProvider