我有很多课程,我试图序列化为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
}
标识符是一个只包含一个字段的类:
public class Identifier {
@JsonProperty("name")
String name = "";
}
我想做的是将标识符更改为:
public class Identifier {
@JsonProperty("name")
String name = "";
@JsonIgnore
IdentifierType type;
}
public Enum IdentifierType {
FOO, BAR, BAZ;
}
然后我想使用'类型'标识符中的字段,用于更改包含这些标识符的对象中标识符字段的名称。
我想用这个替换SomethingFoo,SomethingBar和SomethingBaz:
public class Something {
@JsonProperty(??????)
Identifier name
// other properties
}
我希望Something.identifier的属性名称为" foo"," bar"或" baz",具体取决于Identifier的值。类型。
或者,我也可以使用标识符进行子类化,而不是使用枚举。
问题在于我试图在对象中使用值(或对象的类型,如果使用子类)来通知包含类的标识符中的属性名称。所以我不知道在不改变包含标识符的每个类的情况下,我想做什么是可能的。
修改
问题是我想要什么' Something'被序列化为其中之一(基于标识符的枚举类型(或子类,如果这是实现此目的的更好方法)):
{
"foo" : {
"name" : "blahblahblah"
}
}
{
"bar" : {
"name" : "blahblahblah"
}
}
{
"baz" : {
"name" : "blahblahblah"
}
}
答案 0 :(得分:4)
这可以使用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);
}
}
答案 1 :(得分:2)
注释的属性值必须是常量,因此您无法更改它。我不确定我在这里看到了什么问题。为什么下面的解决方案不起作用? @JsonProperty
只是告诉ObjectMapper
Json字段的名称应该是什么。
public class Something {
@JsonProperty(value = "id")
Identifier identifier
// other properties
}
如果您序列化了其中一个对象,那就会出现这样的情况:
{
"id": FOO,
...
}
如果value - "id"
没有@JsonProperty
,则只使用字段名称:
{
"identifier": FOO,
...
}
杰克逊有很多方法可以自定义序列化和反序列化对象。如果您希望序列化有更多信息(例如,如果您向Enum添加任何字段)或想要更改它的序列化方式,那么有办法做到这一点。例如,如果您希望将Enum序列化为对象在 Jackson 2.1.2 @JsonFormat
你可以做到:
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum Identifier {...}
修改强>
我不认为将数据序列化为上述格式必然是有意义的,因为您不再将对象表示为JSON,因为您将其表示为不同的对象。您已经在对象上有一个字段,用于区分该对象的Identifier
是什么,您可以在其他任何地方使用该字段。如果您真的想按照上面描述的方式将数据序列化,我相信您必须为此类型实现自己的JsonSerializer
(至少对于Jackson 2.1):
public SomethingSerializer extends JsonSerializer<Something> {
// Define serialization methods
...
}
然后扩展SimpleModule,添加序列化程序,并使用ObjectMapper注册模块:
ObjectMapper mapper = new ObjectMapper();
SimpleModule testModule = new SimpleModule("MyModule", new Version(1, 0, 0, null));
testModule.addSerializer(new SomethingSerializer());
mapper.registerModule(testModule);
的示例