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

Jackson JSON反序列化:如何根据JSON值为对象成员赋值?

Jackson 特殊嵌套JSON反序列化实现方案

你的判断是对的,这种非固定键、数组内动态配对的JSON结构,没法直接通过简单的@JsonProperty注解映射,两种常用实现方式如下,按需选择即可。

方案1:树模型手动取值(快速实现)

不用额外编写自定义反序列化类,直接先将JSON解析为Jackson通用的JsonNode树结构,逐层遍历节点取值赋值,适合单次使用、逻辑简单的场景:

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class ParseTest {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        // 替换为你的完整JSON字符串
        String json = """
            {
                "ContainerValues": [
                    {
                        "ParentAttribute": "QuantityContained",
                        "RowList": [
                            {
                                "Values": [
                                    {"Name": "Code", "ValuesByLocale": {"en-US": "GRM"}},
                                    {"Name": "Value", "ValuesByLocale": {"en-US": "4.0"}}
                                ]
                            }
                        ]
                    }
                ]
            }
            """;
        JsonNode root = mapper.readTree(json);
        POJO pojo = new POJO();

        for (JsonNode container : root.get("ContainerValues")) {
            // 按需加过滤条件,比如只处理QuantityContained类型的节点
            if (!"QuantityContained".equals(container.path("ParentAttribute").asText())) {
                continue;
            }
            for (JsonNode row : container.path("RowList")) {
                String code = null;
                String matchValue = null;
                for (JsonNode valItem : row.path("Values")) {
                    String itemName = valItem.path("Name").asText();
                    String enUsVal = valItem.path("ValuesByLocale").path("en-US").asText();
                    if ("Code".equals(itemName)) {
                        code = enUsVal;
                    } else if ("Value".equals(itemName)) {
                        matchValue = enUsVal;
                    }
                }
                if ("GRM".equals(code)) {
                    pojo.grmValue = matchValue;
                    // 如果只需要取第一个匹配项,在这里加break终止循环即可
                }
                // 其他编码对应的字段可以在这里扩展判断,比如Code为KGM时赋值给kgmValue
            }
        }
        System.out.println(pojo.grmValue); // 输出4.0
    }
}

class POJO {
    public String grmValue;
}

方案2:自定义反序列化器(可复用)

如果这个POJO需要在多个接口、多处逻辑中反序列化,就编写独立的自定义反序列化器注册到Jackson,后续直接调用readValue就能自动完成映射,不需要重复写遍历逻辑:
首先编写反序列化器实现:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;

public class POJODeserializer extends StdDeserializer<POJO> {

    public POJODeserializer() {
        this(null);
    }

    public POJODeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public POJO deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException {
        JsonNode root = parser.getCodec().readTree(parser);
        POJO pojo = new POJO();

        for (JsonNode container : root.path("ContainerValues")) {
            for (JsonNode row : container.path("RowList")) {
                String code = null;
                String val = null;
                for (JsonNode item : row.path("Values")) {
                    String name = item.path("Name").asText();
                    String localeVal = item.path("ValuesByLocale").path("en-US").asText();
                    if ("Code".equals(name)) {
                        code = localeVal;
                    } else if ("Value".equals(name)) {
                        val = localeVal;
                    }
                }
                if ("GRM".equals(code)) {
                    pojo.grmValue = val;
                }
            }
        }
        return pojo;
    }
}

注册反序列化器后使用:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;

public class DeserializeDemo {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addDeserializer(POJO.class, new POJODeserializer());
        mapper.registerModule(module);

        // 直接读取JSON即可完成字段自动赋值
        POJO pojo = mapper.readValue(你的JSON字符串, POJO.class);
    }
}

注意点:

  • 代码中用path()方法取节点,相比get()可以避免节点不存在时抛出空指针,适配可能缺字段的非严格JSON结构
  • 如果需要支持其他语言,把硬编码的en-US替换成你需要的语言标识即可
  • 如果存在多行GRM的记录,默认会取最后一次遍历到的值,需要取第一个值的话在赋值后加break终止循环就行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 15:39:15