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

使用Jackson YAML库生成含User标识的YAML文件失败求助

问题:Jackson YAML生成格式不符,如何让每个对象前显示"User"?

我在用Jackson YAML库生成YAML文件时,没法得到预期格式。我要保存的是DataTest对象列表,相关代码如下:

DataTest类定义

@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonTypeName("User")
@Builder
public class DataTest
{
   @JsonProperty("ID")
   private int userID;

   @JsonProperty("Name")
   private String userName;

   @JsonProperty("Address")
   private String streetAddress;

   @JsonProperty("City")
   private String theCity;
}

注:该类使用Lombok简化代码,同时添加了Jackson注解。

DataList类定义(存放对象列表)

@JsonRootName(value = "ListOfUsers")
public class DataList extends ArrayList<DataTest>
{
   private static final long serialVersionUID = 7112953850878936075L;

   public DataList()
   {
   }

   // 其他构造方法
}

测试数据类SomeData

public class SomeData
{
   public static String[] theNames = {
         "Jimmy Dean",
         "John Sheridan",
         "John Chriton",
         "James Kirk",
         "River Tan"
   };

   public static String[] theAddresses = {
         "12 Riverview Drive",
         "233X Blue Sector",
         "2nd Room",
         "Captain's Quarters",
         "3rd Berth"
   };

   public static String[] theCities = {
         "Greenview",
         "Babylon 5",
         "Moya the Ship",
         "USS Enterprise",
         "Serenity"
   };
}

生成YAML的ServiceIO类

public class ServiceIO
{
   private static ServiceIO mySelf = null;

   private final ObjectMapper theMapper;
   private final File theFile;

   private ServiceIO()
   {
      theFile = new File("./files/users.yml");
      theMapper = new ObjectMapper(new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER))
                                                    .enable(SerializationFeature.WRAP_ROOT_VALUE)
                                                    .enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
   }

   public void saveServices(DataList theInfo)
   {
      try
      {
         theMapper.writeValue(theFile,theInfo);
      }
      catch(Exception exe)
      {
         exe.printStackTrace();
      }
  
   }

   public static ServiceIO getInstance()
   {
      if(mySelf == null)
         mySelf = new ServiceIO();
  
      return(mySelf);
   }
}

测试类YamlTest

public class YamlTest
{
   public static void main(String[] args)
   {
      DataList list = new DataList();
  
     for(int inc = 0; inc < 5; inc++)
     {
        DataTest test = DataTest.builder().userID(inc+1).userName(SomeData.theNames[inc])
                                .streetAddress(SomeData.theAddresses[inc]).theCity(SomeData.theCities[inc])
                                .build();
        list.add(test);
     }
 
     ServiceIO service = ServiceIO.getInstance();
     service.saveServices(list);
   }
}

期望的YAML格式

ListOfUsers:
  - User:
      ID: 1
      Name: "Jimmy Dean"
      Address: "12 Riverview Drive"
      City: "Greenview"
  - User:
      ID: 2
      Name: "John Sheridan"
      Address: "233X Blue Sector"
      City: "Babylon 5"
  - User:
      ID: 3
      Name: "John Chriton"
      Address: "2nd Room"
      City: "Moya the Ship"
  - User:
      ID: 4
      Name: "James Kirk"
      Address: "Captain's Quarters"
      City: "USS Enterprise"
  - User:
      ID: 5
      Name: "River Tan"
      Address: "3rd Berth"
      City: "Serenity"

实际生成的YAML格式

ListOfUsers:
- ID: 1
  Name: "Jimmy Dean"
  Address: "12 Riverview Drive"
  City: "Greenview"
- ID: 2
  Name: "John Sheridan"
  Address: "233X Blue Sector"
  City: "Babylon 5"
- ID: 3
  Name: "John Chriton"
  Address: "2nd Room"
  City: "Moya the Ship"
- ID: 4
  Name: "James Kirk"
  Address: "Captain's Quarters"
  City: "USS Enterprise"
- ID: 5
  Name: "River Tan"
  Address: "3rd Berth"
  City: "Serenity"

核心需求是每个DataTest对象前要有"User"行,但实际生成的内容里没有,请问哪里出错了?怎么调整才能得到预期格式?


解决办法

问题原因

你添加的@JsonTypeName("User")注解默认只在多态序列化场景下生效——也就是当DataTest对象被当作它的父类/接口类型序列化时,Jackson才会自动添加类型名称作为包装键。但现在你直接序列化DataTest对象,Jackson不会主动用"User"去包装它。

调整方案

给DataTest类添加@JsonTypeInfo注解,明确指定类型信息的包含方式为用对象包装,这样每个DataTest实例都会被"User"键包裹。

修改后的DataTest类代码:

@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonTypeName("User")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@Builder
public class DataTest
{
   @JsonProperty("ID")
   private int userID;

   @JsonProperty("Name")
   private String userName;

   @JsonProperty("Address")
   private String streetAddress;

   @JsonProperty("City")
   private String theCity;
}

验证效果

修改后重新运行测试类,生成的YAML就会和你预期的一致,每个DataTest对象都会被"User"节点包裹。

备选方案(无需多态支持时)

如果不需要多态序列化的特性,也可以手动给DataTest加一层包装类:

@Data
public class UserWrapper {
    @JsonProperty("User")
    private DataTest data;
}

然后把DataList改成ArrayList<UserWrapper>,在添加对象时把DataTest包装进UserWrapper里。不过这种方式不如用Jackson的类型注解简洁。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 00:02:06