You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

不使用第三方库将API返回JSON转换为指定结构Java Map的实现问题

需求说明

调用返回JSON结构的API,无需依赖第三方JSON库,将源响应转换为指定结构的Java对象。

源API响应载荷

{
    "customerId": "23408068569991",
    "data": [
        {
            "nodeId": "HTS",
            "subscriptionId": "P_HTS_Video_1072",
            "subscriptionName": "HTS_Video_1053",
            "subscriptionDescription": "P_HTS_Video_1072",
            "amountCharged": 0.0,
            "statusCode": "0000",
            "adjustmentType": null,
            "startDate": "2021-09-28 07:41:29",
            "endDate": "2021-10-18 07:29:40"
        }
    ],
    "links": [],
    "statusCode": "0000",
    "statusMessage": "0 Success.",
    "transactionId": "12677889909988"
}

目标转换结构

{
  "customerId": "string",
  "transactionId": "string",
  "statusMessage": "string",
  "supportMessage": "string",
  "services": {
    "vas_hlr": {
      "statusCode": "2000",
      "data": [
        {
          "subscriptionId": "P_HTS_Video_1072",
          "subscriptionProviderId": "HTC",
          "subscriptionName": "CHTS_Video_1053",
          "subscriptionDescription": "P_HTS_Video_1072",
          "subscriptionStatus": "Inactive",
          "subscriptionType": "Adhoc",
          "subscriptionLength": null,
          "registrationChannel": null,
          "startDate": "2019-04-30",
          "endDate": "2019-05-06",
          "subscriptionPaymentSource": "Airtime",
          "amountCharged": 50,
          "sendSMSNotification": true,
          "beneficiaryId": null,
          "auto-renew": true,
          "email": null,
          "partnerId": "String",
          "partnerName": "String",
          "lastDeductionChargeDate": "String"
        }
      ]
    }
  }
}

原有代码问题点

  1. 类型强转错误:源响应的data字段是数组类型,原代码直接强转为Map<String, SubscriptionService>会抛出ClassCastException
  2. 字段映射逻辑缺失:源和目标结构存在字段名差异、格式转换需求(如日期截断为yyyy-MM-dd),且目标结构有大量固定默认值需要填充,原代码未做对应处理
  3. 缺少无第三方库的JSON解析逻辑:原代码依赖提前解析好的SubscriptionService对象,未实现原始JSON字符串到Java对象的转换逻辑
修正实现

1. 极简JSON解析工具类(无第三方依赖)

仅适配当前业务场景的JSON解析,无需兼容通用JSON格式,满足轻量化需求:

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SimpleJsonParser {
    // 匹配JSON键值对
    private static final Pattern KV_PATTERN = Pattern.compile("\"(\\w+)\":\\s*(\"?([^\",}\\[\\]]+)\"?|\\[|\\{)");
    // 匹配数组内的JSON对象
    private static final Pattern ARRAY_OBJ_PATTERN = Pattern.compile("\\{[^}]+}");

    public static Map<String, Object> parse(String json) {
        Map<String, Object> result = new HashMap<>();
        Matcher matcher = KV_PATTERN.matcher(json);
        while (matcher.find()) {
            String key = matcher.group(1);
            String value = matcher.group(3);
            String typeFlag = matcher.group(2);
            if ("[".equals(typeFlag)) {
                // 解析数组
                List<Map<String, Object>> array = new ArrayList<>();
                int arrayStart = json.indexOf('[', matcher.end()) + 1;
                int arrayEnd = json.indexOf(']', arrayStart);
                String arrayContent = json.substring(arrayStart, arrayEnd);
                Matcher objMatcher = ARRAY_OBJ_PATTERN.matcher(arrayContent);
                while (objMatcher.find()) {
                    array.add(parse(objMatcher.group()));
                }
                result.put(key, array);
            } else if ("{".equals(typeFlag)) {
                // 嵌套对象,当前场景不需要可忽略
                continue;
            } else {
                // 普通值处理
                if ("null".equals(value)) value = null;
                else if (value != null && value.contains(".")) {
                    try {
                        result.put(key, Double.parseDouble(value));
                        continue;
                    } catch (NumberFormatException ignored) {}
                }
                result.put(key, value);
            }
        }
        return result;
    }
}

2. 调整转换逻辑代码

import java.util.*;

public class ComvivaCustomerSubscriptions extends APIResponse {
    private String customerId;
    private String statusMessage;
    private String transactionId;
    private String supportMessage;
    private Map<String, SubscriptionService> services;
    private APIError apiError;

    // 新增:从原始JSON字符串构建目标对象的入口方法
    public void convertFromRawJson(String rawJson) {
        Map<String, Object> sourceMap = SimpleJsonParser.parse(rawJson);
        // 填充顶层公共字段
        this.customerId = (String) sourceMap.get("customerId");
        this.transactionId = (String) sourceMap.get("transactionId");
        this.statusMessage = (String) sourceMap.get("statusMessage");
        this.supportMessage = ""; // 按业务需求填默认值

        // 构建services结构
        this.services = new HashMap<>();
        SubscriptionService vasHlrService = new SubscriptionService();
        vasHlrService.setStatusCode("2000"); // 固定默认值

        List<Map<String, Object>> sourceDataList = (List<Map<String, Object>>) sourceMap.get("data");
        List<Subscription> targetDataList = new ArrayList<>();
        for (Map<String, Object> sourceItem : sourceDataList) {
            Subscription targetItem = new Subscription();
            // 字段直接映射
            targetItem.setSubscriptionId((String) sourceItem.get("subscriptionId"));
            targetItem.setSubscriptionDescription((String) sourceItem.get("subscriptionDescription"));
            targetItem.setAmountCharged(((Double) sourceItem.get("amountCharged")).longValue());
            // 字段转换处理
            targetItem.setSubscriptionProviderId((String) sourceItem.get("nodeId"));
            String sourceName = (String) sourceItem.get("subscriptionName");
            targetItem.setSubscriptionName("C" + sourceName); // 源HTS_xxx转目标CHTS_xxx
            String rawStartDate = (String) sourceItem.get("startDate");
            targetItem.setStartDate(rawStartDate.split(" ")[0]); // 截断日期到年月日
            String rawEndDate = (String) sourceItem.get("endDate");
            targetItem.setEndDate(rawEndDate.split(" ")[0]);
            // 填充固定默认值
            targetItem.setSubscriptionStatus("Inactive");
            targetItem.setSubscriptionType("Adhoc");
            targetItem.setSubscriptionPaymentSource("Airtime");
            targetItem.setSendSMSNotification(true);
            targetItem.setAutoRenew(true);
            // 其余null值字段无需额外处理
            targetDataList.add(targetItem);
        }
        vasHlrService.setData(targetDataList);
        this.services.put("vas_hlr", vasHlrService);
    }

    // 原有joinServices方法按需保留,此处省略getter/setter
}

// 新增依赖类定义
class SubscriptionService {
    private String statusCode;
    private List<Subscription> data;
    // getter/setter省略
    public String getStatusCode() { return statusCode; }
    public void setStatusCode(String statusCode) { this.statusCode = statusCode; }
    public List<Subscription> getData() { return data; }
    public void setData(List<Subscription> data) { this.data = data; }
}

class Subscription {
    private String subscriptionId;
    private String subscriptionProviderId;
    private String subscriptionName;
    private String subscriptionDescription;
    private String subscriptionStatus;
    private String subscriptionType;
    private Integer subscriptionLength;
    private String registrationChannel;
    private String startDate;
    private String endDate;
    private String subscriptionPaymentSource;
    private Long amountCharged;
    private Boolean sendSMSNotification;
    private String beneficiaryId;
    private Boolean autoRenew;
    private String email;
    private String partnerId;
    private String partnerName;
    private String lastDeductionChargeDate;
    // 此处省略所有getter/setter
}

调用示例

public class Main {
    public static void main(String[] args) {
        String rawApiResponse = "你的源API返回的JSON字符串";
        ComvivaCustomerSubscriptions target = new ComvivaCustomerSubscriptions();
        target.convertFromRawJson(rawApiResponse);
        // 后续可直接使用target对象,或自行序列化为JSON字符串
    }
}

内容的提问来源于stack exchange,提问作者olanrewajufcb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 03:06:03