どのように私は、ジャクソンのリスト包まれた項目のリストをアンラップしますか?

Mridang Agarwalla:

私はこれに似ているBeanを持っています:

public class Product {

    public String id;
    public String vendor;
    public Set<Image> images;
}

public class Image {

    public String originalSrc;
}

私はこれに似ている私のJSONをデシリアライズしようとしています:

{
  "id": "gid:\/\/mysite\/Product\/1853361520730",
  "vendor": "gadgetdown",
  "images": {
    "edges": [
      {
        "node": {
          "originalSrc": "https:\/\/cdn.something.com"
        }
      },
      {
        "node": {
          "originalSrc": "https:\/\/cdn.something.com"
        }
      }
    ]
  }

私はそれぞれのように、オブジェクトをデシリアライズすることができないんだimageオブジェクトがでラップされnodeたオブジェクトと総称してedgesオブジェクト。


編集:明確にするために、私は豆を使用して経由して、これを達成するためにしたくないと、この例では、簡素化され、JSONペイロード内のすべての配列項目は、この中に包まれているedgesnode表現。

マイケルZiober:

すべてのリストは以下のような構造を持っている場合:

{
  "images": {
    "edges": [
      {
        "node": {
          "entry": "entry-value"
        }
      }
    ]
  }
}

各リストであるJSON Objectとのedges性質と、アレイ内の各要素は、によってラップされるJSON Objectnodeプロパティ。このような構造のために、私たちは、からのものと同様の一般的なデシリアライザを書くことができます1つのより高いレベルのリストにオブジェクトの内部リストをデシリアライズ-ジャクソン質問。

例のSetデシリアライザ:

class InnerSetDeserializer extends JsonDeserializer<Set> implements ContextualDeserializer {

  private final JavaType propertyType;

  public InnerSetDeserializer() {
    this(null);
  }

  public InnerSetDeserializer(JavaType propertyType) {
    this.propertyType = propertyType;
  }

  @Override
  public Set deserialize(JsonParser p, DeserializationContext context) throws IOException {
    p.nextToken(); // SKIP START_OBJECT
    p.nextToken(); // SKIP any FIELD_NAME

    CollectionType collectionType = getCollectionType(context);
    List<Map<String, Object>> list = context.readValue(p, collectionType);

    p.nextToken(); // SKIP END_OBJECT

    return list.stream().map(Map::values).flatMap(Collection::stream).collect(Collectors.toSet());
  }

  private CollectionType getCollectionType(DeserializationContext context) {
    TypeFactory typeFactory = context.getTypeFactory();
    MapType mapType =
        typeFactory.constructMapType(
            Map.class, String.class, propertyType.getContentType().getRawClass());

    return typeFactory.constructCollectionType(List.class, mapType);
  }

  @Override
  public JsonDeserializer<?> createContextual(DeserializationContext context, BeanProperty property) {
    return new InnerSetDeserializer(property.getType());
  }
}

我々は使用することができ、以下の通りです:

class Product {

  private String id;
  private String vendor;

  @JsonDeserialize(using = InnerSetDeserializer.class)
  private Set<Image> images;

  // getters, setters
}

例のアプリ:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.type.MapType;
import com.fasterxml.jackson.databind.type.TypeFactory;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class JsonApp {

  public static void main(String[] args) throws IOException {
    File jsonFile = new File("./resources/test.json");

    ObjectMapper mapper = new ObjectMapper();
    Product product = mapper.readValue(jsonFile, Product.class);
    System.out.println(product);
  }
}

上記のコードを印刷:

Product{id='gid://mysite/Product/1853361520730', vendor='gadgetdown', images=[Image{originalSrc='https://cdn.something.com'}, Image{originalSrc='https://cdn.something.com'}]}

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=229940&siteId=1