当前位置: 首页 > 知识库问答 >
问题:

Jackson-在不使用自定义序列化程序的情况下更改映射密钥名称

焦宁
2023-03-14

使用Jackson序列化Person类时,Person是:

public class Person {

    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "My name is "+name+" ("+age+")";
    }

}

我得到以下输出:

Map<Person, String> map = new HashMap<>();
Person john = new Person("John", 20);
map.put(john, "abc");

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.writeValue(System.out, map); //1
objectMapper.writeValue(System.out, john); //2

1:

{"My name is John (20)":"abc"}

2:

{"name":"John","age":20}

有没有一种简单的方法(没有自定义序列化器)来更改map键,以使用name属性而不是#1中的toString输出,而不会丢失#2中的Person对象的序列化输出,并且不改变toString返回值?我希望有一个注释为getName做到这一点,但似乎找不到它。

共有1个答案

韩涵衍
2023-03-14

自定义序列化程序和addKeySerializer似乎是一种更好的方法,尽管创建模块、添加序列化程序或KeySerializer,然后向映射程序注册模块有点麻烦。

如果由于某种原因(如您所述),您无法使用自定义序列化程序。下面是一些可能对你有所帮助的选项

两者都产生输出

{"John":"abc"}

在编写地图时,但保持单个对象不变

{"name":"John","age":20}

要在输出上映射的Java 8流

根据实际对象的复杂程度,与简单的示例相比,您可以在WriteValue调用期间或之前简单地进行映射。

    mapper.writeValue(System.out,
                      map.entrySet().stream().collect(
                         Collectors.toConcurrentMap(
                            k -> k.getKey().getName(),
                            Function.identity())));

在集合上实现JsonSerializable

如果您能够将html" target="_blank">集合更改为扩展HashMap的自定义版本。

class PersonHashMap extends HashMap<Person, String> implements JsonSerializable {

    @Override
    public void serialize(JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeStartObject();
        for (Entry<Person, String> e : entrySet()) {
            jsonGenerator.writeStringField(e.getKey().getName(), e.getValue());
        }
        jsonGenerator.writeEndObject();
    }

    @Override
    public void serializeWithType(JsonGenerator jsonGenerator, SerializerProvider serializerProvider, TypeSerializer typeSerializer) throws IOException {
        .
        .
        .
    }
}

缺点是需要控制地图的初始化,才能执行以下操作:

Map<Person, String> map = new PersonHashMap();

但话说回来,这就是所需的全部,不需要额外的模块,也不需要像使用JsonSerializer那样注册对象映射器。

 类似资料:
  • 问题内容: 我有这个架构: 我想用Gson序列化Data对象,并得到类似的东西: 为此,我必须对学生部分使用自定义序列化程序,以便Gson仅打印学校的ID。但是对于学校来说,我必须有正常的序列化器。 我如何只用一个Gson对象就能完成所有工作? 问题答案: 您可以编写自定义序列化器,如下所示:

  • 我正在使用以下方法创建地图: 它给出了以下输出: 我需要向键添加类变量名,如下所示:

  • 下面的代码再现了这个问题: 上面的代码不做其他注册“自定义”序列化程序的事情(只是委托回原始序列化程序),但它生成的JSON没有null属性: {“第一个”:“鲍勃”,“最后一个”:“巴克”} 我读过许多看似相关的SO文章,但没有一篇能让我找到解决方案。我尝试在序列化时显式地将映射器设置为,但没有成功。 我唯一的线索是JavaDoc for JsonSerializer中的一条注释: 注意:永远不

  • 问题内容: 遵循在使用GSON解析JSON时使用枚举中的建议,我正在尝试序列化其键是使用Gson 的映射。 考虑以下类别: 两个问题: 为什么打印而不是? 我该如何打印? 问题答案: Gson对密钥使用了专用的序列化器。默认情况下,它使用将要用作键的对象的。对于类型,基本上就是常量的名称。,默认为类型,仅当将序列化为JSON值(对名称除外)时才使用。 使用来构建你的实例。

  • 问题内容: 我有两个要使用Jackson序列化为JSON的Java类: 我想将Item序列化为此JSON: 用户序列化为仅包含。我还将能够将所有用户对象序列化为JSON,例如: 所以我想我需要为此编写一个自定义的序列化程序并尝试过: 我使用来自Jackson How-to:Custom Serializers的 代码对JSON进行了序列化: 但是我得到这个错误: 如何在Jackson上使用自定义序

  • 问题内容: 我有两个要使用Jackson序列化为JSON的Java类: 我想将Item序列化为此JSON: 用户序列化为仅包含。我还将能够将所有用户对象序列化为,例如: 所以我想我需要为此编写一个自定义的序列化程序并尝试过: 我使用来自的以下代码对JSON进行了序列化: 但是我得到这个错误: 如何在Jackson上使用自定义序列化程序? 这就是我对Gson的处理方式: 但是我现在需要和Jackso