如何从嵌套JSON中仅显示指定字段
问题梳理与代码修正
咱们一步步来修正代码,帮你实现从嵌套JSON中仅提取name字段,并输出你想要的格式。目前你的代码存在几个关键问题,我逐个给你解决:
1. 修正对象模型的字段类型
你的Car类里values字段定义为CarValues,但JSON中的values是数组结构,应该对应List<CarValue>类型。同时要调整自定义反序列化器的适配类型:
修改后的Car.java
public class Car { private String shop; private String date; @JsonDeserialize(using = CustomDeserializer.class) private List<CarValue> values; // 修正为List<CarValue>,匹配JSON数组结构 // Getters and Setters @Override public String toString() { StringBuilder str = new StringBuilder("=================================\r\n"); str.append("Shop: ").append(shop).append("\r\n") .append("Date: ").append(date).append("\r\n"); for(CarValue ld : values) { str.append("\t").append("Name: ").append(ld.getName()).append("\r\n"); // 按需只输出name字段,其他字段可以注释掉 } return str.toString(); } }
2. 修复自定义反序列化器逻辑
原来的反序列化器返回类型错误,也没有正确遍历JSON数组提取name。修改后让它专门处理数组,只提取每个元素的name字段:
修改后的CustomDeserializer.java
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class CustomDeserializer extends JsonDeserializer<List<CarValue>> { @Override public List<CarValue> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { ObjectCodec oc = p.getCodec(); JsonNode node = oc.readTree(p); List<CarValue> valueList = new ArrayList<>(); // 遍历JSON数组,逐个提取name字段 if (node.isArray()) { for (JsonNode itemNode : node) { CarValue value = new CarValue(); value.setName(itemNode.get("name").asText()); // 仅保留name字段 valueList.add(value); } } return valueList; } }
3. 调整CarResponse的toString输出逻辑
原来的toString方法有逻辑bug:循环刚执行一次就return,导致输出不完整,格式也不符合预期。调整后让它输出你想要的格式:
修改后的CarResponse.java
import java.time.LocalDate; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.List; public class CarResponse { List<Car> car = new ArrayList<>(); public List<Car> getCar() { return car; } public void setCar(List<Car> car) { this.car = car; } @Override public String toString() { StringBuilder sb = new StringBuilder(); // 输出当前时区的起始时间(和你示例格式一致) ZonedDateTime zdt = LocalDate.now().atStartOfDay(ZoneId.systemDefault()); sb.append(zdt.toString()).append(System.lineSeparator()); for (Car ld : car) { sb.append("Date: ").append(ld.getDate()).append(System.lineSeparator()); // 格式化输出仅包含name的数组 sb.append("Values:["); for (int i = 0; i < ld.getValues().size(); i++) { CarValue cv = ld.getValues().get(i); sb.append("{\"name\":\"").append(cv.getName()).append("\"}"); // 最后一个元素不加逗号 if (i != ld.getValues().size() - 1) { sb.append(","); } } sb.append("]}").append(System.lineSeparator()); } return sb.toString(); } }
4. 测试代码示例
假设你用Jackson解析JSON,测试代码可以这样写:
import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; public class Main { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); CarResponse response = mapper.readValue(new File("data.json"), CarResponse.class); System.out.println(response.toString()); } }
最终输出效果
运行后就能得到你期望的控制台输出:
2021-02-27T09:00+01:00[Europe/Zagreb] Date: 1573599600000 Values:[{"name":"Audi Xl"},{"name":"Audi i"},{"name":"Bmw Xl"},{"name":"Citroen"}]}
内容的提问来源于stack exchange,提问作者user9347049




