Spring Java POST 一个字段可以是不同数据类型的端点
Spring Java POST endpoint that can have a field be different data types
我正在开发 Java Spring 启动 HTTP 服务应用程序。我目前在 @RestController
中定义了一个 POST 端点。这个名为 processRequest
的控制器采用带有 @RequestBody
注释的名为 Info
的对象。
现在,我设置了它,用户可以根据我这样定义的 Info
class 发送 JSON:
//Sample JSON Payload
{
"name": "Bob",
"age": 26,
"hobby": biking
}
//Sample Object
@RequiredArgsConstructor
public class Info {
public final String name;
public final int age;
public final String hobby
}
我想知道的是响应其中一个字段作为不同数据类型发送的情况。例如:
//JSON payload with different datatype for a field
{
"name": "Bob",
age: 26,
"hobby": ["biking", "hiking"] //This is supposed to be a string but it's an array.
}
是否可以保持端点属性相同但处理不同的数据类型?也许我可以创建另一个字段不同的 class 并且 spring 会自动创建与输入匹配的字段?我很好奇解决这个问题的最佳方法是什么。
您可以使用JsonNode
来更改字段。如下:
public class Info {
public String name;
public int age;
public JsonNode hobby;
@Schema(description = "")
@Valid
@JsonIgnore
public List<String> getHobbies() {
// if hobby is array create Java object and return
// else if hobby is String create List, add the string to it and return it.
// or some other solution of your choice and requirement
}
}
在这个特定示例中,爱好可以是单个值或多个值,我将依赖 Jackson ACCEPT_SINGLE_VALUE_AS_ARRAY
反序列化功能。
这可以在 application.properties:
的应用程序范围内配置
spring.jackson.deserialization.accept-single-value-as-array=true
或者可以为特定字段启用此功能:
@RequiredArgsConstructor
public class Info {
public final String name;
public final int age;
@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
public final List<String> hobby
}
对于更复杂的情况,Jackson 建议您编写一个带有特定类型字段的包装器,以提供应反序列化哪种类型的提示。例如:
public class InfoWrapper {
private String type;
@JsonTypeInfo(use = Id.NAME, property = "type", include = As.EXTERNAL_PROPERTY)
@JsonSubTypes(value = {
@JsonSubTypes.Type(value = PersonInfo.class, name = "person")
})
private Info info;
}
public interface Info {}
@RequiredArgsConstructor
public class PersonInfo implements Info {
public final String name;
public final int age;
public final String hobby
}
所以,如果你想发送一个包含PersonInfo
的JSON,你可以使用下面的JSON:
{
"type": "person",
"info": {
"name": "Bob",
"age": 26,
"hobby": "biking"
}
}
如果您需要对要执行的操作进行更高级的控制,您可以编写自定义反序列化程序并使用 @JsonDeserialize
注释应用它。
我正在开发 Java Spring 启动 HTTP 服务应用程序。我目前在 @RestController
中定义了一个 POST 端点。这个名为 processRequest
的控制器采用带有 @RequestBody
注释的名为 Info
的对象。
现在,我设置了它,用户可以根据我这样定义的 Info
class 发送 JSON:
//Sample JSON Payload
{
"name": "Bob",
"age": 26,
"hobby": biking
}
//Sample Object
@RequiredArgsConstructor
public class Info {
public final String name;
public final int age;
public final String hobby
}
我想知道的是响应其中一个字段作为不同数据类型发送的情况。例如:
//JSON payload with different datatype for a field
{
"name": "Bob",
age: 26,
"hobby": ["biking", "hiking"] //This is supposed to be a string but it's an array.
}
是否可以保持端点属性相同但处理不同的数据类型?也许我可以创建另一个字段不同的 class 并且 spring 会自动创建与输入匹配的字段?我很好奇解决这个问题的最佳方法是什么。
您可以使用JsonNode
来更改字段。如下:
public class Info {
public String name;
public int age;
public JsonNode hobby;
@Schema(description = "")
@Valid
@JsonIgnore
public List<String> getHobbies() {
// if hobby is array create Java object and return
// else if hobby is String create List, add the string to it and return it.
// or some other solution of your choice and requirement
}
}
在这个特定示例中,爱好可以是单个值或多个值,我将依赖 Jackson ACCEPT_SINGLE_VALUE_AS_ARRAY
反序列化功能。
这可以在 application.properties:
的应用程序范围内配置spring.jackson.deserialization.accept-single-value-as-array=true
或者可以为特定字段启用此功能:
@RequiredArgsConstructor
public class Info {
public final String name;
public final int age;
@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
public final List<String> hobby
}
对于更复杂的情况,Jackson 建议您编写一个带有特定类型字段的包装器,以提供应反序列化哪种类型的提示。例如:
public class InfoWrapper {
private String type;
@JsonTypeInfo(use = Id.NAME, property = "type", include = As.EXTERNAL_PROPERTY)
@JsonSubTypes(value = {
@JsonSubTypes.Type(value = PersonInfo.class, name = "person")
})
private Info info;
}
public interface Info {}
@RequiredArgsConstructor
public class PersonInfo implements Info {
public final String name;
public final int age;
public final String hobby
}
所以,如果你想发送一个包含PersonInfo
的JSON,你可以使用下面的JSON:
{
"type": "person",
"info": {
"name": "Bob",
"age": 26,
"hobby": "biking"
}
}
如果您需要对要执行的操作进行更高级的控制,您可以编写自定义反序列化程序并使用 @JsonDeserialize
注释应用它。