如何使用Gson将服务端命名对象响应转换为指定数组结构?
使用Gson将命名对象结构转换为指定数组结构
刚好之前处理过类似的JSON结构转换需求,用Gson来实现其实很清晰,我给你拆解下具体步骤和代码示例:
需求回顾
先明确下我们要处理的结构:
- 服务端原始响应(命名对象结构):
{ "Value_1": { "Foo": "True", "Bar": "False"}, "Value_2": { "Foo": "False", "Bar": "False"}, "Value_3": { "Foo": "False", "Bar": "True"} }
- 期望转换结果(数组结构):
[{"Name": "Value_1", "Details": [{"Name": "Foo", "Value": "True"}, {"Name": "Bar", "Value": "False"}]}, {"Name": "Value_2", "Details": [{"Name": "Foo", "Value": "False"}, {"Name": "Bar", "Value": "False"}]}, {"Name": "Value_3", "Details": [{"Name": "Foo", "Value": "False"}, {"Name": "Bar", "Value": "True"}]}]
实现方案
方案一:定义实体类(推荐,可读性高)
这种方式通过Java实体类映射目标结构,后续业务处理更方便。
1. 定义目标结构的实体类
// 对应结果数组中的每个顶层对象 class TopLevelItem { private String Name; private List<DetailItem> Details; // 全参构造器,方便初始化 public TopLevelItem(String name, List<DetailItem> details) { this.Name = name; this.Details = details; } // Gson序列化/反序列化需要无参构造,若用Lombok可加@NoArgsConstructor public TopLevelItem() {} // 可选:添加getter/setter,或者用Lombok的@Data注解简化 } // 对应Details数组中的每个详情对象 class DetailItem { private String Name; private String Value; public DetailItem(String name, String value) { this.Name = name; this.Value = value; } public DetailItem() {} }
2. 编写转换逻辑
import com.google.gson.Gson; import com.google.gson.JsonObject; import com.google.gson.reflect.TypeToken; import java.util.ArrayList; import java.util.List; import java.util.Map; public class JsonTransformDemo { public static void main(String[] args) { // 模拟服务端返回的JSON字符串 String rawResponse = "{ \"Value_1\": { \"Foo\": \"True\", \"Bar\": \"False\"}, \"Value_2\": { \"Foo\": \"False\", \"Bar\": \"False\"}, \"Value_3\": { \"Foo\": \"False\", \"Bar\": \"True\"} }"; Gson gson = new Gson(); // 1. 将原始JSON解析为泛型Map,方便遍历键值对 Map<String, JsonObject> rawMap = gson.fromJson(rawResponse, new TypeToken<Map<String, JsonObject>>() {}.getType()); // 2. 遍历Map,逐个转换为目标结构 List<TopLevelItem> resultList = new ArrayList<>(); for (Map.Entry<String, JsonObject> entry : rawMap.entrySet()) { String topName = entry.getKey(); JsonObject detailJson = entry.getValue(); // 转换Details列表 List<DetailItem> details = new ArrayList<>(); for (Map.Entry<String, com.google.gson.JsonElement> detailEntry : detailJson.entrySet()) { details.add(new DetailItem(detailEntry.getKey(), detailEntry.getValue().getAsString())); } resultList.add(new TopLevelItem(topName, details)); } // 3. 将结果List序列化为JSON字符串(如果需要) String targetJson = gson.toJson(resultList); System.out.println(targetJson); } }
方案二:直接操作Json对象(无需实体类)
如果只是临时转换,不想定义实体类,可以直接用Gson的JsonObject和JsonArray来构建目标结构:
import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import java.util.Map; public class DirectJsonTransform { public static void main(String[] args) { String rawResponse = "{ \"Value_1\": { \"Foo\": \"True\", \"Bar\": \"False\"}, \"Value_2\": { \"Foo\": \"False\", \"Bar\": \"False\"}, \"Value_3\": { \"Foo\": \"False\", \"Bar\": \"True\"} }"; Gson gson = new Gson(); // 解析原始JSON为JsonObject JsonObject rawObj = gson.fromJson(rawResponse, JsonObject.class); // 构建目标JsonArray JsonArray targetArray = new JsonArray(); for (Map.Entry<String, com.google.gson.JsonElement> entry : rawObj.entrySet()) { // 构建顶层对象 JsonObject topItem = new JsonObject(); topItem.addProperty("Name", entry.getKey()); // 构建Details数组 JsonArray detailsArray = new JsonArray(); JsonObject detailJson = entry.getValue().getAsJsonObject(); for (Map.Entry<String, com.google.gson.JsonElement> detailEntry : detailJson.entrySet()) { JsonObject detailItem = new JsonObject(); detailItem.addProperty("Name", detailEntry.getKey()); detailItem.addProperty("Value", detailEntry.getValue().getAsString()); detailsArray.add(detailItem); } topItem.add("Details", detailsArray); targetArray.add(topItem); } // 输出结果JSON System.out.println(gson.toJson(targetArray)); } }
关键说明
- 用
TypeToken解析泛型Map是因为Gson无法直接识别泛型类型,需要通过TypeToken获取类型信息。 - 如果你的项目使用Lombok,可以给实体类添加
@Data、@AllArgsConstructor、@NoArgsConstructor注解,省去手动编写构造器和getter/setter的麻烦。 - 两种方案各有优劣:实体类方案适合长期维护的业务场景,直接操作Json对象适合临时转换需求。
内容的提问来源于stack exchange,提问作者advice
相关产品推荐
相关产品推荐

