{
"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"}
]
}
// 頂層
@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
// 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());
}
}
@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 智能匹配。手動遍歷僅作為動態結構/調試備選。