将空 Jackson 节点反序列化到集合时遇到问题
Having trouble deserialzing null Jackson node to a collection
当我的 JsonNode
没有价值时,我正在 deserializing
测试一个 collection
对象。我希望对象等于 null
.
这就是我正在尝试的:
public class ImmutableDiscoveredUrlDeserializer extends JsonDeserializer<ImmutableDiscoveredUrl> {
String parentUrl;
Double parentUrlSentiment;
Set<String> childUrls;
Boolean isParentVendorUrl;
Map<TagClassification, Set<String>> parentUrlArticleTags;
/*
* (non-Javadoc)
* @see com.fasterxml.jackson.databind.JsonDeserializer#deserialize(com.fasterxml.jackson.core.JsonParser, com.fasterxml.jackson.databind.DeserializationContext)
*/
@Override
public ImmutableDiscoveredUrl deserialize(JsonParser p, DeserializationContext ctx)
throws IOException {
JsonNode node = p.readValueAsTree();
parentUrl = defaultIfNull(node.get("parentUrl").asText(), null);
childUrls = defaultIfNull(parseChildUrls(node), emptySet());
isParentVendorUrl = defaultIfNull(Boolean.valueOf(node.get("isParentVendorUrl").asText()), null);
parentUrlArticleTags = defaultIfNull(parseArticleTags(node.get("parentUrlArticleTags")), emptyMap());
return ImmutableDiscoveredUrl.discoveredUrl().parentUrl(parentUrl)
.parentUrlSentiment(parentUrlSentiment).childUrls(childUrls)
.isParentVendorUrl(isParentVendorUrl).parentUrlArticleTags(parentUrlArticleTags);
}
private Set<String> parseChildUrls(JsonNode node) throws IOException {
ObjectMapper tagsMapper = new ObjectMapper();
return tagsMapper.convertValue(node, new TypeReference<Set<String>>() {});
}
private Map<TagClassification, Set<String>> parseArticleTags(JsonNode node) throws IOException {
ObjectMapper tagsMapper = new ObjectMapper();
return tagsMapper.convertValue(node, new TypeReference<Set<String>>() {});
}
但我收到 MismatchedInputException
,说明没有要映射的内容。如何让 ObjectMapper
变为 return 空值?
因为你已经有了 JsonNode
你可以使用 ObjectMapper#convertValue
:
@Test
public void converts_null_to_null() throws Exception {
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree("{\"foo\":null}");
JsonNode foo = jsonNode.get("foo");
Set<String> result = mapper.convertValue(foo, new TypeReference<Set<String>>() {});
assertNull(result);
}
请注意,如果您传入普通 Map
,convertValue()
将 不会 按预期工作。在您的情况下,您需要删除 defaultIfNull
并自己检查 null
:
if (node.get("parentUrlArticleTags") !== null) {
parentUrlArticleTags = parseArticleTags(node.get("parentUrlArticleTags"));
}
在我的例子中,我遇到了一些不同的问题,为了获得
Cannot deserialize instance of `java.util.HashSet` out of START_OBJECT token
at [Source: (String)"{"bbc":"firstbckt","ssg":{"751fad0":"751fad0","be0eb99":"be0eb99"}}"
这是我的 POJO
import java.io.Serializable;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuppressWarnings("serial")
public class BulkUploadRsp implements Serializable {
private String bbc;
private Map<String, String> ssgs = Maps.newHashMap();
//..
public void setSsgs(Set<String> ssgs) {
this.ssgs = ssgs.stream().collect(Collectors.toMap(ssg -> ssg, ssg -> ssg));
}
}
问题是:我有这个以 set*
开头的 util 方法。将其重命名为 setSsgs(Set<String> ssgs)
有助于解决问题
当我的 JsonNode
没有价值时,我正在 deserializing
测试一个 collection
对象。我希望对象等于 null
.
这就是我正在尝试的:
public class ImmutableDiscoveredUrlDeserializer extends JsonDeserializer<ImmutableDiscoveredUrl> {
String parentUrl;
Double parentUrlSentiment;
Set<String> childUrls;
Boolean isParentVendorUrl;
Map<TagClassification, Set<String>> parentUrlArticleTags;
/*
* (non-Javadoc)
* @see com.fasterxml.jackson.databind.JsonDeserializer#deserialize(com.fasterxml.jackson.core.JsonParser, com.fasterxml.jackson.databind.DeserializationContext)
*/
@Override
public ImmutableDiscoveredUrl deserialize(JsonParser p, DeserializationContext ctx)
throws IOException {
JsonNode node = p.readValueAsTree();
parentUrl = defaultIfNull(node.get("parentUrl").asText(), null);
childUrls = defaultIfNull(parseChildUrls(node), emptySet());
isParentVendorUrl = defaultIfNull(Boolean.valueOf(node.get("isParentVendorUrl").asText()), null);
parentUrlArticleTags = defaultIfNull(parseArticleTags(node.get("parentUrlArticleTags")), emptyMap());
return ImmutableDiscoveredUrl.discoveredUrl().parentUrl(parentUrl)
.parentUrlSentiment(parentUrlSentiment).childUrls(childUrls)
.isParentVendorUrl(isParentVendorUrl).parentUrlArticleTags(parentUrlArticleTags);
}
private Set<String> parseChildUrls(JsonNode node) throws IOException {
ObjectMapper tagsMapper = new ObjectMapper();
return tagsMapper.convertValue(node, new TypeReference<Set<String>>() {});
}
private Map<TagClassification, Set<String>> parseArticleTags(JsonNode node) throws IOException {
ObjectMapper tagsMapper = new ObjectMapper();
return tagsMapper.convertValue(node, new TypeReference<Set<String>>() {});
}
但我收到 MismatchedInputException
,说明没有要映射的内容。如何让 ObjectMapper
变为 return 空值?
因为你已经有了 JsonNode
你可以使用 ObjectMapper#convertValue
:
@Test
public void converts_null_to_null() throws Exception {
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree("{\"foo\":null}");
JsonNode foo = jsonNode.get("foo");
Set<String> result = mapper.convertValue(foo, new TypeReference<Set<String>>() {});
assertNull(result);
}
请注意,如果您传入普通 Map
,convertValue()
将 不会 按预期工作。在您的情况下,您需要删除 defaultIfNull
并自己检查 null
:
if (node.get("parentUrlArticleTags") !== null) {
parentUrlArticleTags = parseArticleTags(node.get("parentUrlArticleTags"));
}
在我的例子中,我遇到了一些不同的问题,为了获得
Cannot deserialize instance of `java.util.HashSet` out of START_OBJECT token
at [Source: (String)"{"bbc":"firstbckt","ssg":{"751fad0":"751fad0","be0eb99":"be0eb99"}}"
这是我的 POJO
import java.io.Serializable;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuppressWarnings("serial")
public class BulkUploadRsp implements Serializable {
private String bbc;
private Map<String, String> ssgs = Maps.newHashMap();
//..
public void setSsgs(Set<String> ssgs) {
this.ssgs = ssgs.stream().collect(Collectors.toMap(ssg -> ssg, ssg -> ssg));
}
}
问题是:我有这个以 set*
开头的 util 方法。将其重命名为 setSsgs(Set<String> ssgs)
有助于解决问题