将带有大量不必要信息的JSON映射到Java对象时的正确方法

时间:2016-10-11 14:44:55

标签: java json jackson mapping

所以我有一个非常大的JSON字符串,有很多嵌套,我收到它作为对REST API调用的响应,我想将它映射到我的java应用程序中的一个对象(目前使用Jackson进行该操作) 。问题是,我需要50%的JSON字符串中提供的信息,其余的根本不需要。在为JSON字符串应该映射到的类建模时,正确的方法是什么?我应该只在对象中创建我需要的字段并告诉映射器忽略其余的字段吗?

如果是这样,该怎么办呢?假设我需要获得1个字段,但结构看起来像这样:

{
   "abc":123,
   "bcd":"qwe",
   "cde":"asd",       
   "def":1,
   "obj":{          
      "av":861,
      "asdf":{
         "id":139204,                       
         "params":{
            "item":139070,
            "level":110
         }
    }
}

我需要获得“level”属性 - 我应该使用某种包装器重新创建所有嵌套还是有更有效的方法来执行此操作?

4 个答案:

答案 0 :(得分:2)

ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

完整示例:

public class Demo {

    public static void main(String[] args) throws IOException {
        String json = "{\n" +
                "  \"abc\": 123,\n" +
                "  \"bcd\": \"qwe\",\n" +
                "  \"cde\": \"asd\",\n" +
                "  \"def\": 1,\n" +
                "  \"obj\": {\n" +
                "    \"av\": 861,\n" +
                "    \"asdf\": {\n" +
                "      \"id\": 139204,\n" +
                "      \"params\": {\n" +
                "        \"item\": 139070,\n" +
                "        \"level\": 110\n" +
                "      }\n" +
                "    }\n" +
                "  }\n" +
                "}";

        ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        MyObj obj = mapper.readValue(json, MyObj.class);

        System.out.println(obj);

    }

    public static class MyObj {
        private String bcd;

        @Override
        public String toString() {
            return "MyObj{" +
                    "bcd='" + bcd + '\'' +
                    '}';
        }

        public String getBcd() {
            return bcd;
        }

        public void setBcd(String bcd) {
            this.bcd = bcd;
        }
    }
}

它将打印:

  

MyObj中{BCD =' QWE'}

因此,您可以随意使用所需的嵌套来定义对象。

如果用这种方式定义对象:

 public static class MyObj {
        private String bcd;
        private NestedObj1 obj;

        @Override
        public String toString() {
            return "MyObj{" +
                    "bcd='" + bcd + '\'' +
                    ", obj=" + obj +
                    '}';
        }

        public String getBcd() {
            return bcd;
        }

        public void setBcd(String bcd) {
            this.bcd = bcd;
        }

        public NestedObj1 getObj() {
            return obj;
        }

        public void setObj(NestedObj1 obj) {
            this.obj = obj;
        }
    }


    public static class NestedObj1 {
        private NestedObj2 asdf;

        @Override
        public String toString() {
            return "NestedObj1{" +
                    "asdf=" + asdf +
                    '}';
        }

        public NestedObj2 getAsdf() {
            return asdf;
        }

        public void setAsdf(NestedObj2 asdf) {
            this.asdf = asdf;
        }
    }

    public static class NestedObj2 {
        private int id;

        @Override
        public String toString() {
            return "NestedObj2{" +
                    "id=" + id +
                    '}';
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }
    }

系统将打印:

  

MyObj {bcd =' qwe',obj = NestedObj1 {asdf = NestedObj2 {id = 139204}}}

正如您所看到的,忽略了所有不必要的json值(未在mapper类中定义)。

答案 1 :(得分:1)

我建议在这种情况下将嵌套的json字符串转换为相应的扁平json字符串。

这可以帮助您避免在JSONObject中循环。

使用maven项目中提供的下述JSONFlattener API可以使嵌套json变平。 关注链接:https://github.com/wnameless/json-flattener

方法: 第1步:使用提到的API展平嵌套的JSON。 因此,在您的情况下,它将转变为:

PUT /config/status HTTP/1.1
Host: example.com
Content-Type: application/json

{ 
  "value": "default" 
}

现在,这个简化的json密钥可以映射到Java POJO。

步骤2:现在根据您的要求,您可以将所需的字段放入POJO中,并将其他字段留在您想要忽略的位置。 为此你可以告诉杰克逊忽略这些领域? (在POJO对象上不存在)在Jackson提供的pojo类中使用类级别注释。(JsonIgnoreProperties)。

这可以帮助您简化解决方案。希望它有所帮助。

答案 2 :(得分:0)

当您的Java表示与json不同时,直接解析为类结构可能不合适。但是,任何格式良好的json都可以相对容易地解析为弱类型的map / list结构。即杰克逊:

Map jsonMap = new ObjectMapper().readValue(json, Map.class);

我们可以使用Java 8库Dynamics来帮助我们在null-safe& amp;中处理这些结构。流利的方式。

public class MyView {
    private final Dynamic data;

    public MyView(Map data) {
        this.data = Dynamic.from(data);
    }

    public String getBcd() {
        return data.get("bcd").asString();
    }

    public int getObjAsdfLevel() {
        return data.dget("obj.asdf.params.level").convert().intoInteger();
    }
}

行动中:

int objAsdfLevel = new MyView(jsonMap).getObjAsdfLevel();
// 110

有关源/文档和更多示例,请参阅https://github.com/alexheretic/dynamics

答案 3 :(得分:0)

克,

如果您对切换到GSON感兴趣,我有一个名为GsonPath的库,可能适合您的需求。该库的目的是提供一个注释处理器,通过生成通常需要编写的样板代码来帮助您展平POJO。

通过使用库,您可以编写类似于以下内容的POJO:

@AutoGsonAdapter
public class SamplePojo {
    int abc;

    String bcd;

    String cds;

    int def;

    @SerializedName("obj.av")
    int av;

    @SerializedName("obj.asdf.id")
    int asdf_id;

    @SerializedName("obj.asdf.params.item")
    int asdf_params_item;

    @SerializedName("obj.asdf.params.level")
    int asdf_params_level;
}

然后您在gson对象中需要做的就是注册一个特殊的TypeAdapterFactory

GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapterFactory(GsonPath.createTypeAdapterFactory());
Gson gson = builder.create();

library中的文档非常全面,如果您有任何问题,请告诉我们!