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

JAXB未转换内部Wrapper DTO求助:需展示POJO字段而非对象引用

解决JSON序列化时自定义对象显示为类名@哈希码的问题

看起来你遇到了JSON序列化时自定义对象没有正确输出字段的问题——那些com.sample.commercewebservices.dto.ComplexTypeWsDTO@xxx的内容其实是对象默认toString()方法的输出,而不是你想要的DTO字段。下面是具体的解决思路和方案:

1. 核心问题:序列化框架未正确识别DTO字段

不管你用的是Jackson(Spring Boot默认)还是Gson这类序列化工具,默认情况下如果没有正确配置,框架会调用对象的toString()方法输出,就会出现这种类名+哈希码的结果。咱们需要让框架知道要序列化对象的实际字段。

针对Jackson(Spring Boot常用场景)

  • 给DTO添加公共Getter方法:Jackson默认通过Getter方法识别字段,给ComplexTypeWsDTO的每个字段补上Getter(Setter可选,反序列化时需要):
class ComplexTypeWsDTO {
    String complexField1;
    String complexField2;
    String complexField3;

    public String getComplexField1() {
        return complexField1;
    }

    public void setComplexField1(String complexField1) {
        this.complexField1 = complexField1;
    }

    // 同理添加complexField2、complexField3的Getter/Setter
}
  • 用Lombok简化代码:如果项目引入了Lombok,直接给ComplexTypeWsDTO加@Data注解,自动生成Getter、Setter、toString等方法,Jackson能直接识别这些字段:
import lombok.Data;

@Data
class ComplexTypeWsDTO {
    String complexField1;
    String complexField2;
    String complexField3;
}
  • 配置Jackson直接序列化字段(无需Getter):如果不想写Getter,可以通过ObjectMapper配置让框架直接访问私有字段:
@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        // 允许序列化所有字段,不管是否有Getter
        objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        return objectMapper;
    }
}

针对Gson

Gson默认会序列化对象的所有字段(包括私有字段),只要你没自定义覆盖默认的toString(),直接序列化就能得到正确结果:

Gson gson = new Gson();
String jsonResponse = gson.toJson(yourResponseWsDTOInstance);

如果需要自定义序列化逻辑,可以创建TypeAdapter来指定ComplexTypeWsDTO的输出格式:

class ComplexTypeWsDTOAdapter extends TypeAdapter<ComplexTypeWsDTO> {
    @Override
    public void write(JsonWriter out, ComplexTypeWsDTO value) throws IOException {
        out.beginObject();
        out.name("complexField1").value(value.complexField1);
        out.name("complexField2").value(value.complexField2);
        out.name("complexField3").value(value.complexField3);
        out.endObject();
    }

    @Override
    public ComplexTypeWsDTO read(JsonReader in) throws IOException {
        // 按需实现反序列化逻辑
        ComplexTypeWsDTO dto = new ComplexTypeWsDTO();
        in.beginObject();
        while (in.hasNext()) {
            switch (in.nextName()) {
                case "complexField1":
                    dto.complexField1 = in.nextString();
                    break;
                case "complexField2":
                    dto.complexField2 = in.nextString();
                    break;
                case "complexField3":
                    dto.complexField3 = in.nextString();
                    break;
            }
        }
        in.endObject();
        return dto;
    }
}

// 使用时注册适配器
Gson gson = new GsonBuilder()
        .registerTypeAdapter(ComplexTypeWsDTO.class, new ComplexTypeWsDTOAdapter())
        .create();

2. 自定义Map的序列化格式(匹配预期响应)

你的预期响应里,Map的value嵌套了complexType数组,而不是直接输出列表。如果要实现这个结构,需要自定义Map的序列化逻辑:

用Jackson实现自定义Map序列化

创建一个序列化器处理Map<Date, List<ComplexTypeWsDTO>>:

public class CustomMapSerializer extends JsonSerializer<Map<Date, List<ComplexTypeWsDTO>>> {
    @Override
    public void serialize(Map<Date, List<ComplexTypeWsDTO>> map, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeStartArray();
        for (Map.Entry<Date, List<ComplexTypeWsDTO>> entry : map.entrySet()) {
            gen.writeStartObject();
            // 自定义日期格式,和预期一致
            gen.writeStringField("key", new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(entry.getKey()));
            gen.writeObjectFieldStart("value");
            gen.writeArrayFieldStart("complexType");
            // 逐个序列化ComplexTypeWsDTO对象
            for (ComplexTypeWsDTO dto : entry.getValue()) {
                gen.writeObject(dto);
            }
            gen.writeEndArray();
            gen.writeEndObject();
            gen.writeEndObject();
        }
        gen.writeEndArray();
    }
}

然后在ResponseWsDTO的mapFieldName字段上添加注解:

class ResponseWsDTO {
    @JsonSerialize(using = CustomMapSerializer.class)
    Map<Date, List<ComplexTypeWsDTO>> mapFieldName;
    String field1;
    String field2;

    // Getter/Setter
}

3. 额外注意事项

  • 避免自定义toString()干扰:如果ComplexTypeWsDTO重写了toString()方法,且不是返回JSON格式内容,某些序列化配置下会优先使用这个方法,所以要么删除自定义toString(),要么让序列化框架忽略它。
  • 统一日期格式:确保序列化后的日期字符串和预期一致,比如Jackson可以通过objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"))配置。

按照上面的步骤处理后,序列化出来的JSON就会像你预期的那样,正确展示ComplexTypeWsDTO的字段内容了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:49:14