java Jackson 序列化的动态属性名称

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25877741/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 08:50:58  来源:igfitidea点击:

Dynamic property name for Hymanson serialization

javajsonHymanson

提问by SlimyTadpole

I have a number of classes I'm trying to serialize to JSON. They're very similar, so I'm wondering if there's a better way to do this than creating 3 very-near-identical classes each time this pattern shows up:

我有许多类要序列化为 JSON。它们非常相似,所以我想知道是否有比每次出现这种模式时创建 3 个非常接近相同的类更好的方法:

public class SomethingFoo {
  @JsonProperty("foo")
  Identifier foo

  // other properties
}

public class SomethingBar {
  @JsonProperty("bar")
  Identifier bar

  // other properties
}

public class SomethingBaz {
  @JsonProperty("baz")
  Identifier baz

  // other properties
}

Identifier is a class that only contains one field:

标识符是一个只包含一个字段的类:

public class Identifier {
  @JsonProperty("name")
  String name = "";
}

What I would like to do, is change Identifier to something like:

我想做的是将 Identifier 更改为:

public class Identifier {
  @JsonProperty("name")
  String name = "";

  @JsonIgnore
  IdentifierType type;
}

public Enum IdentifierType {
  FOO, BAR, BAZ;
}

I would then like to use the 'type' field, within Identifier, to change the name of the Identifier field in the objects that contain those Identifiers.

然后我想使用标识符中的“类型”字段来更改包含这些标识符的对象中标识符字段的名称。

I would then like to do replace SomethingFoo, SomethingBar, and SomethingBaz with this:

然后我想用这个替换SomethingFoo、SomethingBar和SomethingBaz:

public class Something {
  @JsonProperty(??????)
  Identifier name

  // other properties
}

I would like the property name of Something.identifier to be "foo", "bar", or "baz", depending on the value of Identifier.type.

我希望Something.identifier 的属性名称为“foo”、“bar”或“baz”,具体取决于Identifier.type 的值。

Alternatively, I could also sub-class Identifier, rather than use an Enum.

或者,我也可以子类标识符,而不是使用枚举。

The problem is that I'm trying to use a value within an object (or the type of the object, if sub-classes are used) to inform the property name in the Identifier's containing class. So I don't know if what I want to do is even possible without changing every class that contains an Identifier.

问题是我试图使用对象中的值(或对象的类型,如果使用子类)来通知标识符包含类中的属性名称。所以我不知道在不更改每个包含标识符的类的情况下我是否可以做我想做的事情。

Edit:

编辑:

The problem is I want 'Something' to be Serialized as one of these (Based on Identifier's enum type (or subclass, if that's a better way to accomplish this)):

问题是我希望将“Something”序列化为其中之一(基于标识符的枚举类型(或子类,如果这是实现此目的的更好方法)):

{
  "foo" : { 
     "name" : "blahblahblah"
  }
}

{
  "bar" : { 
     "name" : "blahblahblah"
  }
}

{
  "baz" : { 
     "name" : "blahblahblah"
  }
}

采纳答案by mkobit

Attribute values for Annotations must be constant, so you cannot change that. I'm not sure I see a problem here. Why would your solution below not work? The @JsonPropertyjust tells the ObjectMapperwhat the name of the Json field should be.

Annotations 的属性值必须是常量,因此您无法更改它。我不确定我在这里看到了问题。为什么下面的解决方案不起作用?在@JsonProperty刚刚告诉ObjectMapperJSON的字段的名称应该是什么。

public class Something {
  @JsonProperty(value = "id")
  Identifier identifier

  // other properties
}

If you serialized one of these objects it would come out to something this:

如果您序列化这些对象之一,它会得到这样的结果:

{
  "id": FOO,
  ...
}

Without having the value - "id"for @JsonPropertyit would just use the field name:

没有value - "id"for@JsonProperty它只会使用字段名称:

{
  "identifier": FOO,
  ...
}

Hymanson has a bunch of ways to customize it serializes and deserializes object. If you want the serialization to have more information (say if you add any fields to your Enum) or want to change how it was serialized there are ways to do that.. For Example, if you wanted the Enum to be serialized as an Object in Hymanson 2.1.2@JsonFormatyou could do:

Hymanson 有很多方法可以自定义它序列化和反序列化对象。如果您希望序列化具有更多信息(例如,如果您向 Enum 添加任何字段)或想要更改它的序列化方式,则有一些方法可以做到这一点。例如,如果您希望将 Enum 序列化为一个对象在Hyman逊 2.1.2@JsonFormat你可以这样做:

@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum Identifier {...}


EDIT:I don't think serializing the data into the format described above necessarily makes sense as you are not really representing the object as JSON anymore as you are representing it as a different object. You already have a field on the object that discriminates what the Identifierfor that object is and you can use that anywhere else. If you really wanted to serialize the data into the way you have described above, I believe you would have to implement your own JsonSerializerfor that type like this (at least for Hymanson 2.1):

编辑:我认为将数据序列化为上述格式不一定有意义,因为您不再真正将对象表示为 JSON,而是将其表示为不同的对象。您已经在对象上有一个字段来区分Identifier该对象的内容,并且您可以在其他任何地方使用它。如果您真的想将数据序列化为上述方式,我相信您必须JsonSerializer像这样为该类型实现自己的数据(至少对于 Hymanson 2.1):

public SomethingSerializer extends JsonSerializer<Something> {
  // Define serialization methods
  ...
}

And then extend SimpleModule, add the serializer, and register the module with ObjectMapper:

然后扩展 SimpleModule,添加序列化器,并使用 ObjectMapper 注册模块:

ObjectMapper mapper = new ObjectMapper();
SimpleModule testModule = new SimpleModule("MyModule", new Version(1, 0, 0, null));
testModule.addSerializer(new SomethingSerializer());
mapper.registerModule(testModule);

Example adapted from HymansonHowToCustomSerializers

改编自HymansonHowToCustomSerializers 的示例

回答by tarush grover

This can be done using JsonSerializer with your custom implementation. Please refer to below code.

这可以通过使用 JsonSerializer 和您的自定义实现来完成。请参考以下代码。

 @JsonSerialize(using = Term.TermSerializer.class)
 public class Term {

//@JsonProperty("field")
private String field;

public Term() {

}

public Term(String field){
    this.field = field;
}

public String getField() {
    return field;
}

public void setField(String field) {
    this.field = field;
}

public static class TermSerializer extends JsonSerializer<Term> {
    @Override public void serialize(Term value, JsonGenerator jsonGenerator, SerializerProvider provider)
        throws IOException {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("price", value.getField());// dynamic field name
        jsonGenerator.writeEndObject();
    }
}

public static void main(String[] args){
    Term term = new Term("color");
    ObjectMapper mapper = new ObjectMapper();
    mapper.enable(SerializationFeature.INDENT_OUTPUT);
    mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
    String jsonString = null;
    try {
        jsonString = mapper.writeValueAsString(term);
    } catch (JsonProcessingException e) {
        e.printStackTrace();
    }
    System.out.println(jsonString);
}

}

}