首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java JSON 反序列化實戰:嵌套結構映射到實體類完整流程

     編輯:程式設計綜合問答

目標 JSON 結構分析

{
  "code": "D1_3300_0000",
  "action": "prepay",
  "title": "繳費 - 浙江電力",
  "form": [                    // ← JSONArray
    {                          // ← JSONObject (bill 類型)
      "type": "bill",
      "name": "bill_id",
      "label": "您查詢賬單如下",
      "options": [             // ← JSONArray
        {"label": "2013年5月", "value": "...", "amount": "13.58"},
        {"label": "2013年6月", "value": "...", "amount": "23.47"}
      ]
    },
    {"type": "string", "label": "戶名", "value": "張三"},  // ← JSONObject (string 類型)
    {"type": "string", "label": "地址", "value": "..."},
    {"type": "string", "label": "違約金(元)", "value": "0"},
    {"type": "string", "label": "總應繳金額(元)", "value": "30.23"}
  ]
}

實體類設計 (FastJSON / Jackson 通用)

// 頂層
@Data
public class FeeResponse {
    private String code;
    private String action;
    private String title;
    private List form;  // 多態列表
}

// form 陣列基類
@Data
public class FormItem {
    private String type;  // "bill" / "string"
    private String name;
    private String label;
    private String value;      // string 類型用
    private List

FastJSON 多態反序列化配置

// 1. 註冊類型映射 (可選,FastJSON 智能匹配字段通常足夠)
ParserConfig.getGlobalInstance().putDeserializer(FormItem.class, 
    new JavaBeanDeserializer(ParserConfig.getGlobalInstance(), 
        JavaBeanInfo.build(FormItem.class, null, ParserConfig.getGlobalInstance()), 
        new FieldDeserializer[0], 0));

// 2. 一鍵解析
String json = "..."; // 上述 JSON
FeeResponse response = JSON.parseObject(json, FeeResponse.class);

// 3. 類型安全訪問
for (FormItem item : response.getForm()) {
    if ("bill".equals(item.getType())) {
        System.out.println("賬單: " + item.getLabel());
        for (Option opt : item.getOptions()) {
            System.out.printf("  %s: %s 元%n", opt.getLabel(), opt.getAmount());
        }
    } else if ("string".equals(item.getType())) {
        System.out.printf("%s: %s%n", item.getLabel(), item.getValue());
    }
}

Jackson 實現 (Spring Boot 默認)

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = BillItem.class, name = "bill"),
    @JsonSubTypes.Type(value = StringItem.class, name = "string")
})
public abstract class FormItem { ... }

@Data
public class BillItem extends FormItem {
    private List

手動節點遍歷 (無實體類場景)

JSONObject root = JSON.parseObject(json);
JSONArray form = root.getJSONArray("form");
for (int i = 0; i < form.size(); i++) {
    JSONObject item = form.getJSONObject(i);
    String type = item.getString("type");
    if ("bill".equals(type)) {
        JSONArray options = item.getJSONArray("options");
        for (int j = 0; j < options.size(); j++) {
            JSONObject opt = options.getJSONObject(j);
            System.out.println(opt.getString("label") + " = " + opt.getString("amount"));
        }
    } else {
        System.out.println(item.getString("label") + ": " + item.getString("value"));
    }
}

常見坑點與解決

問題解決
字段名不匹配 (如 JSON bill_id vs Java billId)@JSONField(name="bill_id") / @JsonProperty("bill_id")
數值類型不一致 (JSON 字符串 "13.58" → Java BigDecimal)FastJSON 自動轉換;Jackson 需 @JsonDeserialize(using=BigDecimalDeserializer.class)
嵌套泛型擦除導致 List<Object> 而非 List<Option>使用 TypeReference: JSON.parseObject(json, new TypeReference(){})
字段缺失導致 null實體類字段用包裝類型 (Integer 而非 int),或 @JSONField(serialize=false)

總結

**優先定義實體類 + 註解驅動反序列化**,複雜多態結構用 @JsonTypeInfo (Jackson) 或 FastJSON 智能匹配。手動遍歷僅作為動態結構/調試備選。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved