当前位置: 首页 > 知识库问答 >
问题:

Gson自定义反序列化以生成不同的json输出

缑赤岩
2023-03-14

我有一个REST Api服务,它给了我以下响应

{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 3,
    "successful": 3,
    "failed": 0
  },
  "hits": {
    "total": 3,
    "max_score": 123,
    "hits": [
      {
        "_index": "123",
        "_type": "bar",
        "_id": "123",
        "_score": 323,
        "_source": {
          "employeeNo": 239,
          "employeeName": "John",
          "employeeRank": 21,
          "employeeNationality": "Indian",
          "employeeNickName": "KingKong"
        }
      },
      {
        "_index": "234",
        "_type": "bar",
        "_id": "124",
        "_score": 324,
        "_source": {
          "employeeNo": 241,
          "employeeName": "Sunny",
          "employeeRank": 19,
          "employeeNickName": "Jakk"
        }
      },
      {
        "_index": "235",
        "_type": "bar",
        "_id": "125",
        "_score": 325,
        "_source": {
          "employeeNo": 251,
          "employeeName": "Pollard",
          "employeeRank": 10
        }
      }
    ]
  },
  "aggregations": {
    "foo": {
      "buckets": [
        {
          "key": 123,
          "doc_count": 123
        }
      ]
    }
  }
}

实际上,我希望json的格式如下所示(应为json)

[
  {
    "employeeNo": 239,
    "employeeName": "John",
    "employeeRank": 21,
    "employeeNationality": "Indian",
    "employeeNickName": "KingKong"
  },
  {
    "employeeNo": 241,
    "employeeName": "Sunny",
    "employeeRank": 19,
    "employeeNickName": "Jakk"
  },
  {
    "employeeNo": 251,
    "employeeName": "Pollard",
    "employeeRank": 10
  }
]

为了实现这一点,我编写了以下代码

List<Map<String, String>> myResults = new ArrayList<Map<String, String>>();
Gson serializer = new GsonBuilder().create(); 
String responseDetails = doHttpPost(urlToQuery, serializer.toJson(requestBody));
Map<String,Object> restResponse = (Map<String,Object>)serializer.fromJson(responseDetails,Object.class);
if(restResponse.containsKey("hits")){
    Map<String, Object> hits = (Map<String, Object>) restResponse.get("hits");
    if(hits.containsKey("hits")) {
        List<Map<String, Object>> hitDetails = (List<Map<String, Object>>) hits.get("hits");
        for (Map<String, Object> hitDetail : hitDetails) {
            Map<String, Object> sources = (Map<String, Object>) hitDetail.get("_source");
            myResults.add(sources);
        }
    }
}

在上面的代码中,我以字符串的形式从REST Api获取响应,并将其放入变量中。此外,我将其反序列化为映射

Map<String,Object> restResponse = (Map<String,Object>)serializer.fromJson(responseDetails,Object.class);

进一步,我迭代它并形成我的预期Json响应。

我的问题是:在这种方法中,为了获得预期的json,我需要再次迭代反序列化的json,并手动形成它。

在反序列化自身的过程中,有没有什么方法可以得到响应json作为fromJson函数的返回。即如下所示

List<Map<String, String>> myResults = serializer.fromJson(responseDetails);

我们可以重写fromJson函数并编写我们自己的自定义反序列化程序来返回列表吗

期待您的建议,甚至其他可以提高性能的方法

如果需要更多说明,请告诉我

共有1个答案

沈栋
2023-03-14

对于REST服务,我通常建议您使用一些JSON到Java模型转换程序/服务,例如JSONUtils(可在Github上获得)

在此转换之后,您将拥有Java模型:

ServiceResult类

import com.fasterxml.jackson.annotation.JsonProperty;

public class ServiceResult {
    @JsonProperty("took")
    public int getTook() {
        return this.took;
    }

    public void setTook(int took) {
        this.took = took;
    }

    int took;

    @JsonProperty("timed_out")
    public boolean getTimed_out() {
        return this.timed_out;
    }

    public void setTimed_out(boolean timed_out) {
        this.timed_out = timed_out;
    }

    boolean timed_out;

    @JsonProperty("_shards")
    public Shards get_shards() {
        return this._shards;
    }

    public void set_shards(Shards _shards) {
        this._shards = _shards;
    }

    Shards _shards;

    @JsonProperty("hits")
    public Hits getHits() {
        return this.hits;
    }

    public void setHits(Hits hits) {
        this.hits = hits;
    }

    Hits hits;

    @JsonProperty("aggregations")
    public Aggregations getAggregations() {
        return this.aggregations;
    }

    public void setAggregations(Aggregations aggregations) {
        this.aggregations = aggregations;
    }

    Aggregations aggregations;

}

碎片类

import com.fasterxml.jackson.annotation.JsonProperty;

public class Shards {
    @JsonProperty("total")
    public int getTotal() {
        return this.total;
    }

    public void setTotal(int total) {
        this.total = total;
    }

    int total;

    @JsonProperty("successful")
    public int getSuccessful() {
        return this.successful;
    }

    public void setSuccessful(int successful) {
        this.successful = successful;
    }

    int successful;

    @JsonProperty("failed")
    public int getFailed() {
        return this.failed;
    }

    public void setFailed(int failed) {
        this.failed = failed;
    }

    int failed;

}

源类别

import com.fasterxml.jackson.annotation.JsonProperty;

public class Source {
    @JsonProperty("employeeNo")
    public int getEmployeeNo() {
        return this.employeeNo;
    }

    public void setEmployeeNo(int employeeNo) {
        this.employeeNo = employeeNo;
    }

    int employeeNo;

    @JsonProperty("employeeName")
    public String getEmployeeName() {
        return this.employeeName;
    }

    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }

    String employeeName;

    @JsonProperty("employeeRank")
    public int getEmployeeRank() {
        return this.employeeRank;
    }

    public void setEmployeeRank(int employeeRank) {
        this.employeeRank = employeeRank;
    }

    int employeeRank;

    @JsonProperty("employeeNationality")
    public String getEmployeeNationality() {
        return this.employeeNationality;
    }

    public void setEmployeeNationality(String employeeNationality) {
        this.employeeNationality = employeeNationality;
    }

    String employeeNationality;

    @JsonProperty("employeeNickName")
    public String getEmployeeNickName() {
        return this.employeeNickName;
    }

    public void setEmployeeNickName(String employeeNickName) {
        this.employeeNickName = employeeNickName;
    }

    String employeeNickName;

}

Hits类

import java.util.List;

import com.fasterxml.jackson.annotation.JsonProperty;

public class Hits {
    @JsonProperty("total")
    public int getTotal() {
        return this.total;
    }

    public void setTotal(int total) {
        this.total = total;
    }

    int total;

    @JsonProperty("max_score")
    public int getMax_score() {
        return this.max_score;
    }

    public void setMax_score(int max_score) {
        this.max_score = max_score;
    }

    int max_score;

    @JsonProperty("hits")
    public List<Hit> getHits() {
        return this.hits;
    }

    public void setHits(List<Hit> hits) {
        this.hits = hits;
    }

    List<Hit> hits;

}

击中类

import com.fasterxml.jackson.annotation.JsonProperty;

public class Hit {
    @JsonProperty("_index")
    public String get_index() {
        return this._index;
    }

    public void set_index(String _index) {
        this._index = _index;
    }

    String _index;

    @JsonProperty("_type")
    public String get_type() {
        return this._type;
    }

    public void set_type(String _type) {
        this._type = _type;
    }

    String _type;

    @JsonProperty("_id")
    public String get_id() {
        return this._id;
    }

    public void set_id(String _id) {
        this._id = _id;
    }

    String _id;

    @JsonProperty("_score")
    public int get_score() {
        return this._score;
    }

    public void set_score(int _score) {
        this._score = _score;
    }

    int _score;

    @JsonProperty("_source")
    public Source get_source() {
        return this._source;
    }

    public void set_source(Source _source) {
        this._source = _source;
    }

    Source _source;

}

Foo类

import java.util.List;

import com.fasterxml.jackson.annotation.JsonProperty;

public class Foo {
    @JsonProperty("buckets")
    public List<Bucket> getBuckets() {
        return this.buckets;
    }

    public void setBuckets(List<Bucket> buckets) {
        this.buckets = buckets;
    }

    List<Bucket> buckets;

}

铲斗等级

import com.fasterxml.jackson.annotation.JsonProperty;

public class Bucket {
    @JsonProperty("key")
    public int getKey() {
        return this.key;
    }

    public void setKey(int key) {
        this.key = key;
    }

    int key;

    @JsonProperty("doc_count")
    public int getDoc_count() {
        return this.doc_count;
    }

    public void setDoc_count(int doc_count) {
        this.doc_count = doc_count;
    }

    int doc_count;

}

聚合类

import com.fasterxml.jackson.annotation.JsonProperty;

public class Aggregations {
    @JsonProperty("foo")
    public Foo getFoo() {
        return this.foo;
    }

    public void setFoo(Foo foo) {
        this.foo = foo;
    }

    Foo foo;

}

现在您有了您的ServiceResult模型,您实际上只需要Source模型。您可以使用java集合流提取它,例如:

import java.io.File;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.io.IOUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class Test {
    public static void main(String[] args) {
        try {

            // String responseDetails = doHttpPost(urlToQuery, serializer.toJson(requestBody));
            // using your json from file
            String responseDetails = new String(IOUtils.toByteArray(new File("test.json").toURI()), "UTF-8");

            Gson serializer = new GsonBuilder().create();
            ServiceResult example = serializer.fromJson(responseDetails, ServiceResult.class);

            // your expected list
            List<Source> sourceList = example.getHits()
                    .getHits()
                    .stream().map(h -> h.get_source())
                    .collect(Collectors.toList());

            // you can just serialize it to json or do whatever you want
            String json = serializer.toJson(sourceList);
            System.out.println(json);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 类似资料:
  • 问题内容: 我在使用Gson解析JSON响应时遇到问题。 JSON字串: 我有这两个课程: 但是当使用Gson解析这个时我有一个异常。我知道这是因为响应数组的第一个元素不是对象,而是整数。 所以问题是,我能以某种方式解决它吗? 问题答案: 您必须编写一个 自定义反序列化器 。我会做这样的事情: 首先,您需要包括一个新的类,而不是已有的两个类: 然后,您需要一个自定义解串器,类似于以下内容: 然后,

  • 问题内容: 确定,所以我编辑了问题,因为它不够清楚。 编辑2 :更新了JSON文件。 我在Android应用程序中使用GSON,我需要解析来自服务器的JSON文件,这些文件有点太复杂了。我不想让我的对象结构太沉重,所以我想简化内容: 所以我的对象的结构将不是JSON文件的结构。 例如,如果在JSON中,我有以下内容: 我不想保留我当前的对象结构,即一个对象,其中包含一个和一个“总计”。但是我只想将

  • 我有一个JestClient(elasticsearch)响应,我试图将其反序列化为一个对象。该对象包含两个DateTime字段,而在响应中,它们是字符串,因此我得到: 所以,我创建了一个自定义反序列化器来解决这个问题…然而,无论我做什么,我总是得到同样的错误。不知何故它没有注册使用它? 最后,我试图解析JestClient响应的代码: 无论我尝试什么,我总是得到上面的错误,我甚至不确定在这一点上

  • 问题内容: 我试图读取JSON文件并将其转换为数组,但是在读取JSON文件后从数组获取空值。我正在为我的班级使用默认构造函数。 JSON文件: 本类: 问题答案: 您的Gson映射与给定的JSON不匹配。默认情况下,Gson通过 确切 名称将JSON属性映射到目标映射中的相应字段。看一眼: 和 属性名称大小写和字段名称大小写不匹配。您需要的是正确映射JSON。要么: 或通过覆盖名称匹配(这更适合J

  • 问题内容: 我正在尝试使用Gson 反序列化a ,值的类型可以变化,值“ in_wanted”可以是a 或a 。 in_wanted为: in_wanted为: 每当“ in_wanted”的值为布尔值时,我都需要该对象,并且需要一个反序列化器以返回null。用Gson做到这一点的最佳方法是什么? 问题答案: 您可以使用自定义解串器来完成此操作。首先,我们应该创建可以表示您的JSON的数据模型。

  • 我有以下JSON示例: 我想使用GSON来反序列化这个JSON字符串,并只获取“famousId”成员的值。 我已经看过了其他答案,似乎我绝对需要为此创建类。 有没有可能不映射POJO,使用JsonParser,JsonElement,JsonArray等反序列化?我已经尝试了几种排列,但没有成功。 我也尝试过以下代码,但也没有按预期工作: 不幸的是,这也不起作用,所以我想一个两部分的问题。。。可