如何在 Java 中声明任何 class 类型的变量或对象
How to declare a variable or Object of any class type in Java
我对 Java 很陌生,我正在尝试使用 Jackson 反序列化 JSON,但我在声明 Object/Variable 类型方面遇到了一些小问题。我会提供所有代码然后解释问题以便于理解。
我有一个具有所需类型值的枚举:
public enum IdentifierTypeValues {
Type1,
Type2,
Type3,
//Constructor and Getter of enum values
}
然后对于这些 type
中的每一个,我有不同的 classes,它们将具有不同的输入并执行完全不同类型的过程:
public class GenerateType1 {
private String name;
private String age;
//Getter and Setter
//Some required process based on these values
}
public class GenerateType2 {
private String address;
private String city;
private String country;
//Getter and Setter
//Some required process based on these values
}
public class GenerateType3 {
private String firstName;
private String lastName;
private String fullName;
//Getter and Setter
//Some required process based on these values
}
现在我有一个包装器 class 用于这些类型的 classes,它将采用基于 enum
和 typeInfo
值的 type
。我希望 typeInfo
值是任何基于 class 的类型,如下所示:
public class TypeSyntax {
private IdentifierTypeValues indeitiferType;
private GenerateType1 / GenerateType2 / GenerateType3 identifierTypeValues;
//Here the identifierTypeValues can have the values for anytype
//How to declare a variable of any of these class type?
}
这是我的 JSON 将用于反序列化的 class。我知道我可以添加这 3 种类型的包装器 class 并为此提供该包装器 class 作为类型 class。像这样:
public class WrapperClass{
private GenerateType1 type1;
private GenerateType2 type2;
private GenerateType3 type3;
}
public class TypeSyntax{
private IdentifierTypeValues indeitiferType;
private WrapperClass identifierTypeValues;
//But using this approach will change my JSON structure which I do not want to do.
}
我的 JSON 结构是这样的,我想以同样的方式保持它。
{
"indeitiferType":"Type1",
"identifierTypeValues":{
"name":"Batman",
"age":"2008"
}
}
有没有办法声明多类型的变量class?或通过保持 json 格式相同来处理此问题的任何更好方法?我尝试搜索,但我无法搜索到底是什么,所以任何帮助都会非常有用。
因为类型标识符存在于与其他属性不同的级别,所以需要包装器 class TypeSyntax
。有几个开放的功能请求向 Jackson 添加包装功能,例如https://github.com/FasterXML/jackson-databind/issues/512
幸运的是,Jackson 通过 @JsonTypeInfo
和 @JsonSubTypes
注释支持多态性。
包装器 class 应如下所示:
public class TypeSyntax {
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
property = "identifierType")
private GenerateTypeBase identifierTypeValues;
// getters and setters (omitted for brevity)
}
GenerateTypeBase
是普通的parentclass
@JsonSubTypes({
@JsonSubTypes.Type(value = GenerateType1.class, name = "Type1"),
@JsonSubTypes.Type(value = GenerateType2.class, name = "Type2"),
})
public abstract class GenerateTypeBase {
private String name;
private String age;
// getters and setters (omitted for brevity)
}
在此不同的childrenclasses将基于identifierType
属性进行实例化。
children 必须扩展此基础 class:
public class GenerateType2 extends GenerateTypeBase {
// additional properties
}
在简短的测试中它将是:
@Test
void wrapperTest() throws IOException {
ObjectMapper mapper = new ObjectMapper();
GenerateType2 a = new GenerateType2();
a.setName("Foo");
a.setAge("13");
TypeSyntax w = new TypeSyntax();
w.setIdentifierTypeValues(a);
String json = mapper.writeValueAsString(w);
System.out.println(json);
}
和输出:
{
"identifierTypeValues":
{
"name":"Foo",
"age":"13"
},
"identifierType":"Type2"
}
反序列化
@Test
void wrapperTest() throws IOException {
ObjectMapper mapper = new ObjectMapper();
String input = "{\"identifierTypeValues\": \"name\":\"Foo\",\"age\":\"13\"},\"identifierType\":\"Type2\"}";
TypeSyntax w = mapper.readValue(new StringReader(input), TypeSyntax.class);
assertAll(
() -> assertEquals(GenerateType2.class, o.getIdentifierTypeValues().getClass()),
() -> assertEquals("13", o.getIdentifierTypeValues().getAge())
);
}
如果您想要更大的灵活性,您可以编写自定义(反)序列化器和/或自定义解析器。使用自定义 TypeIdResolver 可以以编程方式将标识符转换为类型,而不是在 @JsonSubTypes
中使用“key-value 对”
我对 Java 很陌生,我正在尝试使用 Jackson 反序列化 JSON,但我在声明 Object/Variable 类型方面遇到了一些小问题。我会提供所有代码然后解释问题以便于理解。
我有一个具有所需类型值的枚举:
public enum IdentifierTypeValues {
Type1,
Type2,
Type3,
//Constructor and Getter of enum values
}
然后对于这些 type
中的每一个,我有不同的 classes,它们将具有不同的输入并执行完全不同类型的过程:
public class GenerateType1 {
private String name;
private String age;
//Getter and Setter
//Some required process based on these values
}
public class GenerateType2 {
private String address;
private String city;
private String country;
//Getter and Setter
//Some required process based on these values
}
public class GenerateType3 {
private String firstName;
private String lastName;
private String fullName;
//Getter and Setter
//Some required process based on these values
}
现在我有一个包装器 class 用于这些类型的 classes,它将采用基于 enum
和 typeInfo
值的 type
。我希望 typeInfo
值是任何基于 class 的类型,如下所示:
public class TypeSyntax {
private IdentifierTypeValues indeitiferType;
private GenerateType1 / GenerateType2 / GenerateType3 identifierTypeValues;
//Here the identifierTypeValues can have the values for anytype
//How to declare a variable of any of these class type?
}
这是我的 JSON 将用于反序列化的 class。我知道我可以添加这 3 种类型的包装器 class 并为此提供该包装器 class 作为类型 class。像这样:
public class WrapperClass{
private GenerateType1 type1;
private GenerateType2 type2;
private GenerateType3 type3;
}
public class TypeSyntax{
private IdentifierTypeValues indeitiferType;
private WrapperClass identifierTypeValues;
//But using this approach will change my JSON structure which I do not want to do.
}
我的 JSON 结构是这样的,我想以同样的方式保持它。
{
"indeitiferType":"Type1",
"identifierTypeValues":{
"name":"Batman",
"age":"2008"
}
}
有没有办法声明多类型的变量class?或通过保持 json 格式相同来处理此问题的任何更好方法?我尝试搜索,但我无法搜索到底是什么,所以任何帮助都会非常有用。
因为类型标识符存在于与其他属性不同的级别,所以需要包装器 class TypeSyntax
。有几个开放的功能请求向 Jackson 添加包装功能,例如https://github.com/FasterXML/jackson-databind/issues/512
幸运的是,Jackson 通过 @JsonTypeInfo
和 @JsonSubTypes
注释支持多态性。
包装器 class 应如下所示:
public class TypeSyntax {
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
property = "identifierType")
private GenerateTypeBase identifierTypeValues;
// getters and setters (omitted for brevity)
}
GenerateTypeBase
是普通的parentclass
@JsonSubTypes({
@JsonSubTypes.Type(value = GenerateType1.class, name = "Type1"),
@JsonSubTypes.Type(value = GenerateType2.class, name = "Type2"),
})
public abstract class GenerateTypeBase {
private String name;
private String age;
// getters and setters (omitted for brevity)
}
在此不同的childrenclasses将基于identifierType
属性进行实例化。
children 必须扩展此基础 class:
public class GenerateType2 extends GenerateTypeBase {
// additional properties
}
在简短的测试中它将是:
@Test
void wrapperTest() throws IOException {
ObjectMapper mapper = new ObjectMapper();
GenerateType2 a = new GenerateType2();
a.setName("Foo");
a.setAge("13");
TypeSyntax w = new TypeSyntax();
w.setIdentifierTypeValues(a);
String json = mapper.writeValueAsString(w);
System.out.println(json);
}
和输出:
{
"identifierTypeValues":
{
"name":"Foo",
"age":"13"
},
"identifierType":"Type2"
}
反序列化
@Test
void wrapperTest() throws IOException {
ObjectMapper mapper = new ObjectMapper();
String input = "{\"identifierTypeValues\": \"name\":\"Foo\",\"age\":\"13\"},\"identifierType\":\"Type2\"}";
TypeSyntax w = mapper.readValue(new StringReader(input), TypeSyntax.class);
assertAll(
() -> assertEquals(GenerateType2.class, o.getIdentifierTypeValues().getClass()),
() -> assertEquals("13", o.getIdentifierTypeValues().getAge())
);
}
如果您想要更大的灵活性,您可以编写自定义(反)序列化器和/或自定义解析器。使用自定义 TypeIdResolver 可以以编程方式将标识符转换为类型,而不是在 @JsonSubTypes