我如何使用 Jackson 展开 JSON 中的特定字段?
How can I unwrap a specific field in a JSON using Jackson?
我有一个 JSON 有效负载,如下所示:
{
"id": 32,
"name": "[Sample] Tomorrow is today, Red printed scarf",
"primary_image": {
"id": 247,
"zoom_url": "www.site.com/in_123__14581.1393831046.1280.1280.jpg",
"thumbnail_url": "www.site.com/in_123__14581.1393831046.220.290.jpg",
"standard_url": "www.site.com/in_123__14581.1393831046.386.513.jpg",
"tiny_url": "www.site.com/in_123__14581.1393831046.44.58.jpg"
}
}
我可以打开特定字段并丢弃所有其他字段吗?换句话说,我可以像这样将它直接绑定到 POJO 吗:
public class Product {
private Integer id;
private String name;
private String standardUrl;
}
Jackson 提供了@JsonUnwrapped 注解。
见下文link:
http://jackson.codehaus.org/1.9.9/javadoc/org/codehaus/jackson/annotate/JsonUnwrapped.html
有很多方法。您需要反序列化、序列化还是两者都需要?
反序列化的一种方法是使用将图像作为树节点的创建器方法:
public static class Product {
private Integer id;
private String name;
private String standardUrl;
public Product(@JsonProperty("id") Integer id,
@JsonProperty("name") String name,
@JsonProperty("primary_image") JsonNode primaryImage) {
this.id = id;
this.name = name;
this.standardUrl = primaryImage.path("standard_url").asText();
}
}
创建者不必是构造函数,您可以有一个仅用于 Jackson 反序列化的静态方法。
不过,您必须定义一个自定义序列化程序来重新序列化它(例如,一个 StdDelegatingSerializer 和一个将字符串包装回 ObjectNode 的转换器)
有多种方法可以给这只猫剥皮,我希望你可以为此使用 Jackson 2,因为它提供了反序列化 Json 数据的好方法,我最喜欢的反序列化功能之一就是我将在这里向您展示(使用 Builder Pattern),因为允许您在构造实例时验证它们(或使它们不可变!)。对你来说,这看起来像这样:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.util.Map;
@JsonDeserialize(builder = Product.Builder.class)
public class Product {
private Integer id;
private String name;
private String standardUrl;
private Product(Builder builder) {
//Here you can make validations for your new instance.
this.id = builder.id;
this.name = builder.name;
//Here you have access to the primaryImage map in case you want to add new properties later.
this.standardUrl = builder.primaryImage.get("standard_url");
}
@Override
public String toString() {
return String.format("id [%d], name [%s], standardUrl [%s].", id, name, standardUrl);
}
@JsonIgnoreProperties(ignoreUnknown = true)
public static class Builder {
private Integer id;
private String name;
private Map<String, String> primaryImage;
public Builder withId(Integer id) {
this.id = id;
return this;
}
public Builder withName(String name) {
this.name = name;
return this;
}
@JsonProperty("primary_image")
public Builder withPrimaryImage(Map<String, String> primaryImage) {
this.primaryImage = primaryImage;
return this;
}
public Product build() {
return new Product(this);
}
}
}
为了测试它,我创建了这个 class:
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
String serialized = "{" +
" \"id\": 32," +
" \"name\": \"[Sample] Tomorrow is today, Red printed scarf\"," +
" \"primary_image\": {" +
" \"id\": 247," +
" \"zoom_url\": \"www.site.com/in_123__14581.1393831046.1280.1280.jpg\"," +
" \"thumbnail_url\": \"www.site.com/in_123__14581.1393831046.220.290.jpg\"," +
" \"standard_url\": \"www.site.com/in_123__14581.1393831046.386.513.jpg\"," +
" \"tiny_url\": \"www.site.com/in_123__14581.1393831046.44.58.jpg\"" +
" }" +
" }";
ObjectMapper objectMapper = new ObjectMapper();
try {
Product deserialized = objectMapper.readValue(serialized, Product.class);
System.out.print(deserialized.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
输出是(使用 Product
中的覆盖 toString()
方法:
id [32], name [[Sample] Tomorrow is today, Red printed scarf], standardUrl [www.site.com/in_123__14581.1393831046.386.513.jpg].
有两种方法可以获得您需要的回复。对于这两种方法,我们都将使用 JsonView。
创建两种类型的 JsonView:
public interface JViews {
public static class Public { }
public static class Product extends Public { }
}
第一种方法
@JsonView(JViews.Public.class)
public class Product {
private Integer id;
private String name;
@JsonIgnore
private Image primaryImage;
@JsonView(JViews.Product.class)
public String getStandardUrl{
return this.primaryImage.getStandardUrl();
}
}
第二种方式
同时使用杰克逊的@JsonView 和@JsonUnwrapped。
@JsonView(JViews.Public.class)
public class Product {
private Integer id;
private String name;
@JsonUnwrapped
private Image primaryImage;
}
public class Image {
private String zoomUrl;
@JsonView(JViews.Product.class)
private String standardUrl;
}
@JsonUnwrapped 注释将您的嵌套对象展平为 Product 对象。而 JsonView 用于过滤可访问的字段。在这种情况下,产品视图只能访问 standardUrl 字段,结果预计为:
{
"id": 32,
"name": "[Sample] Tomorrow is today, Red printed scarf",
"standard_url": "url"
}
如果您在不使用视图的情况下展平嵌套对象,结果将如下所示:
{
"id": 32,
"name": "[Sample] Tomorrow is today, Red printed scarf",
"id":1,
"standard_url": "url",
"zoom_url":"",
...
}
我有一个 JSON 有效负载,如下所示:
{
"id": 32,
"name": "[Sample] Tomorrow is today, Red printed scarf",
"primary_image": {
"id": 247,
"zoom_url": "www.site.com/in_123__14581.1393831046.1280.1280.jpg",
"thumbnail_url": "www.site.com/in_123__14581.1393831046.220.290.jpg",
"standard_url": "www.site.com/in_123__14581.1393831046.386.513.jpg",
"tiny_url": "www.site.com/in_123__14581.1393831046.44.58.jpg"
}
}
我可以打开特定字段并丢弃所有其他字段吗?换句话说,我可以像这样将它直接绑定到 POJO 吗:
public class Product {
private Integer id;
private String name;
private String standardUrl;
}
Jackson 提供了@JsonUnwrapped 注解。
见下文link:
http://jackson.codehaus.org/1.9.9/javadoc/org/codehaus/jackson/annotate/JsonUnwrapped.html
有很多方法。您需要反序列化、序列化还是两者都需要?
反序列化的一种方法是使用将图像作为树节点的创建器方法:
public static class Product {
private Integer id;
private String name;
private String standardUrl;
public Product(@JsonProperty("id") Integer id,
@JsonProperty("name") String name,
@JsonProperty("primary_image") JsonNode primaryImage) {
this.id = id;
this.name = name;
this.standardUrl = primaryImage.path("standard_url").asText();
}
}
创建者不必是构造函数,您可以有一个仅用于 Jackson 反序列化的静态方法。
不过,您必须定义一个自定义序列化程序来重新序列化它(例如,一个 StdDelegatingSerializer 和一个将字符串包装回 ObjectNode 的转换器)
有多种方法可以给这只猫剥皮,我希望你可以为此使用 Jackson 2,因为它提供了反序列化 Json 数据的好方法,我最喜欢的反序列化功能之一就是我将在这里向您展示(使用 Builder Pattern),因为允许您在构造实例时验证它们(或使它们不可变!)。对你来说,这看起来像这样:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.util.Map;
@JsonDeserialize(builder = Product.Builder.class)
public class Product {
private Integer id;
private String name;
private String standardUrl;
private Product(Builder builder) {
//Here you can make validations for your new instance.
this.id = builder.id;
this.name = builder.name;
//Here you have access to the primaryImage map in case you want to add new properties later.
this.standardUrl = builder.primaryImage.get("standard_url");
}
@Override
public String toString() {
return String.format("id [%d], name [%s], standardUrl [%s].", id, name, standardUrl);
}
@JsonIgnoreProperties(ignoreUnknown = true)
public static class Builder {
private Integer id;
private String name;
private Map<String, String> primaryImage;
public Builder withId(Integer id) {
this.id = id;
return this;
}
public Builder withName(String name) {
this.name = name;
return this;
}
@JsonProperty("primary_image")
public Builder withPrimaryImage(Map<String, String> primaryImage) {
this.primaryImage = primaryImage;
return this;
}
public Product build() {
return new Product(this);
}
}
}
为了测试它,我创建了这个 class:
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
String serialized = "{" +
" \"id\": 32," +
" \"name\": \"[Sample] Tomorrow is today, Red printed scarf\"," +
" \"primary_image\": {" +
" \"id\": 247," +
" \"zoom_url\": \"www.site.com/in_123__14581.1393831046.1280.1280.jpg\"," +
" \"thumbnail_url\": \"www.site.com/in_123__14581.1393831046.220.290.jpg\"," +
" \"standard_url\": \"www.site.com/in_123__14581.1393831046.386.513.jpg\"," +
" \"tiny_url\": \"www.site.com/in_123__14581.1393831046.44.58.jpg\"" +
" }" +
" }";
ObjectMapper objectMapper = new ObjectMapper();
try {
Product deserialized = objectMapper.readValue(serialized, Product.class);
System.out.print(deserialized.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
输出是(使用 Product
中的覆盖 toString()
方法:
id [32], name [[Sample] Tomorrow is today, Red printed scarf], standardUrl [www.site.com/in_123__14581.1393831046.386.513.jpg].
有两种方法可以获得您需要的回复。对于这两种方法,我们都将使用 JsonView。
创建两种类型的 JsonView:
public interface JViews {
public static class Public { }
public static class Product extends Public { }
}
第一种方法
@JsonView(JViews.Public.class)
public class Product {
private Integer id;
private String name;
@JsonIgnore
private Image primaryImage;
@JsonView(JViews.Product.class)
public String getStandardUrl{
return this.primaryImage.getStandardUrl();
}
}
第二种方式
同时使用杰克逊的@JsonView 和@JsonUnwrapped。
@JsonView(JViews.Public.class)
public class Product {
private Integer id;
private String name;
@JsonUnwrapped
private Image primaryImage;
}
public class Image {
private String zoomUrl;
@JsonView(JViews.Product.class)
private String standardUrl;
}
@JsonUnwrapped 注释将您的嵌套对象展平为 Product 对象。而 JsonView 用于过滤可访问的字段。在这种情况下,产品视图只能访问 standardUrl 字段,结果预计为:
{
"id": 32,
"name": "[Sample] Tomorrow is today, Red printed scarf",
"standard_url": "url"
}
如果您在不使用视图的情况下展平嵌套对象,结果将如下所示:
{
"id": 32,
"name": "[Sample] Tomorrow is today, Red printed scarf",
"id":1,
"standard_url": "url",
"zoom_url":"",
...
}