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

是否有自定义Json序列化器模式以不同方式序列化属性(包括属性的键名)?

诸龙野
2023-03-14

我有一个类需要序列化

public class Abc
{
 private long age;
 private JaxBElement<Foo> fooWrapper;
 // other properties
}

预期的输出JSON是

{
 "age": 24,
 "my_own_key": "my_own_value" // the key should not be "fooWrapper"

一个限制是不能修改原始类Abc,因为它是从xjc生成的,我还不想使用绑定来探索自定义类。

我已经为JaxBElement尝试了自定义序列化程序、bean修饰符等,它们都允许我控制序列化。但它们只以房产的价值为依据。他们不允许我在“关键值”级别更改内容。这是问题的关键。在调用自定义序列化程序来控制该值之前,已为属性写出键。

例如,只有在Jackson系统发出密钥后,才会调用我的自定义序列化程序

 "fooWrapper": // now for the value part, let me invoke the custom serializer 

因此,输出JSON始终包含"foWrapper"键。

{ "fooWrapper": { "any-key": "any-value" } }
// the fooWrapper is already emitted out. That is what needs to be controlled.

我的任务是在更高的级别上控制序列化,这样键和值都可以控制。因此,当类Abc被序列化时,fooWrapper属性根本不应该被写成键,应该调用一些自定义序列化程序。

另一个限制是,像Abc这样的类可能有这样的JaxBElement。这是不知道的时间提前。因此,需要有一种通用的方法来附加自定义序列化程序。

伪询问实际上是,我们能够将自定义序列化程序附加到任何具有匹配模式的属性的类,以便序列化程序可以控制写入的属性(或整个键值Blob)的名称。

此外,这个问题本身并不特定于JaxBElement。它可以是任何财产。问题更多地与受控序列化有关,包括正在写入的密钥。

共有2个答案

汤飞翮
2023-03-14

如果你想控制键值对的序列化,你不仅需要为JaxBElement注册自定义序列化程序

由于它不是通用的解决方案,您也可以尝试创建MixIn类或接口,并提供额外的配置:

interface MixInA {

    @JsonSerialize(using = JAXBElementJsonSerializer.class)
    @JsonProperty("newProperty")
    JAXBElement<Foo> getFooWrapper();
}

另见:

  • @JSonIgnore注释的等效代码设置是什么?
  • 使Jackson序列化器覆盖特定的忽略字段

这种解决方案的缺点是,您必须找到所有必须注册MixIn类或接口的类型。如果字段不同,您需要创建许多不同的getter或许多不同的MixIn接口来覆盖它们。

所以,最灵活的解决方案可能是实现定制com。fasterxml。杰克逊。数据绑定。AnnotationIntrospector对于给定类型,可以返回自定义序列化器和自定义名称。简单的例子:

class DynamicJaxbAnnotationIntrospector extends AnnotationIntrospector {

    @Override
    public Version version() {
        return new Version(1, 0, 0, "Dynamic JaxbElement", "your.package", "jackson.dynamic.jaxb");
    }

    @Override
    public Object findSerializer(Annotated am) {
        if (am.getRawType() == JAXBElement.class) {
            return new JAXBElementJsonSerializer();
        }
        return super.findSerializer(am);
    }

    @Override
    public PropertyName findNameForSerialization(Annotated a) {
        if (a.getRawType() == JAXBElement.class) {
            return new PropertyName("newProperty");
        }
        return super.findNameForSerialization(a);
    }
}

另请参阅下面的文章“如何使用它”:

  • 如何将枚举序列化为对象形状和默认字符串

黄聪
2023-03-14

也许你只是使用了不正确的序列化程序。这篇文章虽然有点陈旧,但应该向你展示如何使用StdSerializer做你想做的事情。

这种序列化程序允许您同时控制键和值。

 类似资料:
  • 问题内容: 是否可能:在类中有一个字段,而在Jackson库中进行序列化/反序列化时却为其使用不同的名称? 例如,我有“ Coordiantes”类。 对于从JSON反序列化,希望具有以下格式: 但是当我序列化对象时,结果应该是这样的: 我试图通过在getter和setter上都应用注释(具有不同的值)来实现此目的: 但我有一个例外: org.codehaus.jackson.map.exc.Un

  • 问题内容: 我如何才能序列化一个特定的属性,但又防止其反序列化回POCO?是否可以使用属性装饰特定属性? 基本上,我正在寻找一个与ShouldSerialize *方法等效的反序列化方法。 我知道我可以编写一个自定义转换器,但是这样做似乎有点过头了。 编辑: 这里还有一些背景。这背后的原因是我的课看起来像: 我需要请求的属性,但是我不希望它反序列化并触发设置程序逻辑。 问题答案: 最简单的方法是将

  • 更新发现了问题——从错误的类继承,需要是JsonConverter。 我有一个类型为System的Location属性的类。数据实体空间的地理。默认的Json。NET serializer输出JSON文本,如下所示: 我想让它发出这样的文本: ...所以在我看来,我应该做的是重写当前在DbGeography类型上使用的任何转换器。 到目前为止,我看到的使用CustomCreationConvert

  • 问题内容: 我需要反序列化一些JSON表示的JavaScript对象为适当的C#类。鉴于自动属性的出色功能,我宁愿将它们放在这些类中,而不是仅包含字段。不幸的是,.NET序列化引擎(至少默认情况下)完全忽略了反序列化的自动属性,而只关心背景字段,而该字段显然不在JavaScript对象中。 鉴于没有标准的方法来命名后备字段并且说实话,我什至不想使用“让我们创建一个看起来像具有C#后备字段的Java

  • 我有以下JSON字符串: 我将把它映射到以下模型: 当反序列化这个JSON字符串时,我希望能够在运行时将这些属性名称映射到不同的名称,如下所示: 例如,在反序列化过程中,我希望将“property1”的名称反序列化为“differen_property_name1”或“differen_property_name2”或“differen_property_name3”。因为我在运行时选择了新名称(

  • 正如标题所述,我正在尝试将自定义属性添加到我返回的序列化对象中。 让我们用以下方法来介绍一个用户: getFirstname、setFirstname 现在在序列化中,我想添加一个属性fullName: Firstname Lastname。 我的实体中有一个getter方法,如下所示: 我的序列化文件如下所示: 我试过了 和其他变体,但我似乎不能得到它的权利。 注意:是的,我已清除缓存并重试 有