反序列化杰克逊中同名但不同类型的属性?
Deserializing attributes of same name but different types in Jackson?
我有一个 REST API,其中 returns 一个 JSON 响应为:
{
"channel" : "JHBHS"
}
有时 returns:
{
"channel": {
"id": 12321,
"name": "Some channel"
}
}
我有一个像这样的 POJO:
public class Event {
private String channel;
@JsonProperty("channel")
private Channel channelObj;
}
public class Channel {
private int id;
private String name;
}
那么,在 Jackson2 中有没有一种方法(除了编写您自己的 自定义反序列化器 )可以帮助我将 channel
映射到 JSON 到 String
类型当它是 String
和 Channel
类型当它是 JSON 对象?
或者换句话说,Jackson 中是否有一种方法可以通过变量的 type
而不仅仅是 name
进行映射?
我可以建议您像这样使用 JsonNode:
class Event {
@JsonProperty("channel")
private JsonNode channelInternal;
private Channel channel;
private String channelStr;
/**
* Custom getter with channel parsing
* @return channel
*/
public Channel getChannel() {
if (channel == null && channelInternal != null) {
if (channelInternal.isObject()) {
int id = channelInternal.get("id").intValue();
String name = channelInternal.get("name").asText();
channel = new Channel(id, name);
}
}
return channel;
}
/**
* Custom getter with channel string parsing
* @return channel string
*/
public String getChannelStr() {
if (channelStr == null && channelInternal != null) {
if (channelInternal.isTextual()) {
channelStr = channelInternal.asText();
}
}
return channelStr;
}
}
或者像这样:
class Event {
private Channel channel;
private String channelStr;
@JsonSetter("channel")
public void setChannelInternal(JsonNode channelInternal) {
if (channelInternal != null) {
if (channelInternal.isTextual()) {
channelStr = channelInternal.asText();
} else if (channelInternal.isObject()) {
int id = channelInternal.get("id").intValue();
String name = channelInternal.get("name").asText();
channel = new Channel(id, name);
}
}
}
public Channel getChannel() {
return channel;
}
public String getChannelStr() {
return channelStr;
}
}
但我认为使用自定义解串器更常见。
这是测试代码
public static void main(String[] args) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
String source1 = "{\n" +
" \"channel\" : \"JHBHS\"\n" +
"}";
String source2 = "{\n" +
" \"channel\": {\n" +
" \"id\": 12321,\n" +
" \"name\": \"Some channel\"\n" +
" }\n" +
"}";
//Test object parsing
Event result = objectMapper.readValue(source2, Event.class);
System.out.println(String.format("%s : %s", result.getChannel().getId(), result.getChannel().getName()));
//Test string parsing
result = objectMapper.readValue(source1, Event.class);
System.out.println(result.getChannelStr());
}
并且输出:
12321 : Some channel
JHBHS
我有一个 REST API,其中 returns 一个 JSON 响应为:
{
"channel" : "JHBHS"
}
有时 returns:
{
"channel": {
"id": 12321,
"name": "Some channel"
}
}
我有一个像这样的 POJO:
public class Event {
private String channel;
@JsonProperty("channel")
private Channel channelObj;
}
public class Channel {
private int id;
private String name;
}
那么,在 Jackson2 中有没有一种方法(除了编写您自己的 自定义反序列化器 )可以帮助我将 channel
映射到 JSON 到 String
类型当它是 String
和 Channel
类型当它是 JSON 对象?
或者换句话说,Jackson 中是否有一种方法可以通过变量的 type
而不仅仅是 name
进行映射?
我可以建议您像这样使用 JsonNode:
class Event {
@JsonProperty("channel")
private JsonNode channelInternal;
private Channel channel;
private String channelStr;
/**
* Custom getter with channel parsing
* @return channel
*/
public Channel getChannel() {
if (channel == null && channelInternal != null) {
if (channelInternal.isObject()) {
int id = channelInternal.get("id").intValue();
String name = channelInternal.get("name").asText();
channel = new Channel(id, name);
}
}
return channel;
}
/**
* Custom getter with channel string parsing
* @return channel string
*/
public String getChannelStr() {
if (channelStr == null && channelInternal != null) {
if (channelInternal.isTextual()) {
channelStr = channelInternal.asText();
}
}
return channelStr;
}
}
或者像这样:
class Event {
private Channel channel;
private String channelStr;
@JsonSetter("channel")
public void setChannelInternal(JsonNode channelInternal) {
if (channelInternal != null) {
if (channelInternal.isTextual()) {
channelStr = channelInternal.asText();
} else if (channelInternal.isObject()) {
int id = channelInternal.get("id").intValue();
String name = channelInternal.get("name").asText();
channel = new Channel(id, name);
}
}
}
public Channel getChannel() {
return channel;
}
public String getChannelStr() {
return channelStr;
}
}
但我认为使用自定义解串器更常见。
这是测试代码
public static void main(String[] args) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
String source1 = "{\n" +
" \"channel\" : \"JHBHS\"\n" +
"}";
String source2 = "{\n" +
" \"channel\": {\n" +
" \"id\": 12321,\n" +
" \"name\": \"Some channel\"\n" +
" }\n" +
"}";
//Test object parsing
Event result = objectMapper.readValue(source2, Event.class);
System.out.println(String.format("%s : %s", result.getChannel().getId(), result.getChannel().getName()));
//Test string parsing
result = objectMapper.readValue(source1, Event.class);
System.out.println(result.getChannelStr());
}
并且输出:
12321 : Some channel
JHBHS