SnakeYAML 2.0反序列化出现Global tag is not allowed异常的解决方法
SnakeYAML 2.0自定义对象序列化与反序列化问题解决
问题场景
自定义User类如下:
package ir.sharif; import java.util.ArrayList; import java.util.List; public class User { int id; String username; String password; List<User> friends = new ArrayList<>(); public User(int id, String username, String password) { this.id = id; this.username = username; this.password = password; } public User() { } // 省略getter和setter方法 }
使用SnakeYAML 2.0序列化User对象的代码:
package ir.sharif; import org.yaml.snakeyaml.Yaml; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) throws IOException { User user = new User(); user.setId(10); user.setUsername("Jack"); user.setPassword("jackSparrow2023"); List<User> friends = new ArrayList<>(); friends.add(new User(1, "Trent", "FCB")); friends.add(new User(2, "Jordan", "LFC")); user.setFriends(friends); Yaml yaml = new Yaml(); yaml.dump(user, new FileWriter("src/main/resources/sample.yml")); } }
生成的sample.yml包含类标签:
!!ir.sharif.User friends: - friends: [] id: 1 password: FCB username: Trent - friends: [] id: 2 password: LFC username: Jordan id: 10 password: jackSparrow2023 username: Jack
尝试直接用yaml.load()反序列化时抛出异常:
Exception in thread "main" Global tag is not allowed: tag:yaml.org,2002:ir.sharif.User in 'reader', line 1, column 1: !!ir.sharif.User ^
原因分析
SnakeYAML 2.0为了安全,默认禁用了全局自定义标签,序列化时自动添加的!!ir.sharif.User属于自定义全局标签,反序列化时会被拦截。
解决方案
方法1:反序列化时指定目标类(无需修改序列化逻辑)
直接使用loadAs()方法明确指定要反序列化的类,无需删除yml中的标签:
package ir.sharif; import org.yaml.snakeyaml.Yaml; import java.io.FileReader; import java.io.IOException; import java.io.Reader; public class Main { public static void main(String[] args) throws IOException { Yaml yaml = new Yaml(); try (Reader reader = new FileReader("src/main/resources/sample.yml")) { // 明确指定目标类 User user = yaml.loadAs(reader, User.class); System.out.println(user.getUsername()); // 输出Jack } } }
方法2:配置SnakeYAML允许自定义标签
如果需要保留load()方法的使用,可以创建Yaml实例时配置Constructor,允许指定的自定义标签:
package ir.sharif; import org.yaml.snakeyaml.constructor.Constructor; import org.yaml.snakeyaml.Yaml; import java.io.FileReader; import java.io.IOException; import java.io.Reader; public class Main { public static void main(String[] args) throws IOException { // 构造器指定目标类,允许该类的标签 Constructor constructor = new Constructor(User.class); Yaml yaml = new Yaml(constructor); try (Reader reader = new FileReader("src/main/resources/sample.yml")) { User user = yaml.load(reader); System.out.println(user.getUsername()); // 输出Jack } } }
方法3:序列化时不输出类标签
如果不需要yml文件中的类标签,可以在序列化时配置DumperOptions关闭标签输出,后续反序列化直接用loadAs():
package ir.sharif; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) throws IOException { User user = new User(); user.setId(10); user.setUsername("Jack"); user.setPassword("jackSparrow2023"); List<User> friends = new ArrayList<>(); friends.add(new User(1, "Trent", "FCB")); friends.add(new User(2, "Jordan", "LFC")); user.setFriends(friends); DumperOptions options = new DumperOptions(); options.setExplicitTag(false); // 关闭显式标签输出 Yaml yaml = new Yaml(options); yaml.dump(user, new FileWriter("src/main/resources/sample.yml")); } }
生成的yml文件不再包含!!ir.sharif.User标签,反序列化时直接用loadAs()即可正常解析。
内容的提问来源于stack exchange,提问作者Harry Redwood
相关产品推荐
相关产品推荐

