Ben*_*min 6 java spring snakeyaml
我有一个 yaml 文件,例如:
# this is the part I don't care about
config:
key-1: val-1
other-config:
lang: en
year: 1906
# below is the only part I care about
interesting-setup:
port: 1234
validation: false
parts:
- on-start: backup
on-stop: say-goodbye
Run Code Online (Sandbox Code Playgroud)
我还有一个适合该interesting-setup部分的 POJO 类
public class InterestingSetup {
int port;
boolean validation;
List<Map<String, String>> parts;
}
Run Code Online (Sandbox Code Playgroud)
我想只加载该interesting-setup部分(与 Spring 中类似@ConfigurationProperties("interesting-setup"))
目前我正在这样做:
Map<String, Object> yamlConfig = yaml.load(yamlFile); # loading the whole file to Map with Object values
Object interestingObject = yamlConfig.get("interesting-setup"); # loading 'interesting-setup' part as an object
Map<String, Object> interestingMap = (Map<String, Object>); # Casting object to Map<String, Object>
String yamlDumped = yaml.dump(interestingMap); # Serialization to String
InterestingSetup finalObject = yaml.load(yamlDumped); # Getting final object from String
Run Code Online (Sandbox Code Playgroud)
关键部分是当我有一个对象 (Map<String, Object>) 并希望将其转换为我的最终类时。为此,我需要将其序列化为字符串,因此过程如下所示:
File -> Map<String, Object> -> Object -> Map<String, Object> -> String -> FinalClass
我想避免相同数据的反序列化和再次序列化。
那么我可以用某种方式Yaml将 映射Map<String, Object>到另一个类吗?我在 API 中看不到这个?
AFAIK,SnakeYAML 库没有提供直接的方法来做到这一点。
您可以尝试调整它并仅使用您需要支持的字段定义容器基类。例如,考虑以下 POJO:
public class Container {
private InterestingSetup interestingSetup;
public InterestingSetup getInterestingSetup() {
return interestingSetup;
}
public void setInterestingSetup(InterestingSetup interestingSetup) {
this.interestingSetup = interestingSetup;
}
@Override
public String toString() {
return "Container{" +
"interestingSetup=" + interestingSetup +
'}';
}
}
Run Code Online (Sandbox Code Playgroud)
哪里,InterestingSetup是你自己的班级:
import java.util.List;
import java.util.Map;
public class InterestingSetup {
private int port;
private boolean validation;
private List<Map<String, String>> parts;
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public boolean isValidation() {
return validation;
}
public void setValidation(boolean validation) {
this.validation = validation;
}
public List<Map<String, String>> getParts() {
return parts;
}
public void setParts(List<Map<String, String>> parts) {
this.parts = parts;
}
@Override
public String toString() {
return "InterestingSetup{" +
"port=" + port +
", validation=" + validation +
", parts=" + parts +
'}';
}
}
Run Code Online (Sandbox Code Playgroud)
有了这些 bean,以下代码就可以按照您的要求工作:
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.representer.Representer;
public class Main {
public static void main(String... args) throws UnsupportedEncodingException {
String yamlString =
"# this is the part I don't care about\n" +
"config:\n" +
" key-1: val-1\n" +
"other-config:\n" +
" lang: en\n" +
" year: 1906\n" +
"# below is the only part I care about\n" +
"interesting-setup:\n" +
" port: 1234\n" +
" validation: false\n" +
" parts:\n" +
" - on-start: backup\n" +
" on-stop: say-goodbye";
// Skip unknown properties
Representer representer = new Representer();
representer.getPropertyUtils().setSkipMissingProperties(true);
// Define the target object type
Constructor constructor = new Constructor(Container.class);
TypeDescription containerTypeDescription = new TypeDescription(Container.class);
// Define how the interesting-setup property should be processed
containerTypeDescription.substituteProperty("interesting-setup", InterestingSetup.class,
"getInterestingSetup", "setInterestingSetup");
constructor.addTypeDescription(containerTypeDescription);
// Finally, parse the YAML
Yaml yaml = new Yaml(constructor, representer);
InputStream inputStream = new ByteArrayInputStream(yamlString.getBytes(StandardCharsets.UTF_8));;
Container container = yaml.load(inputStream);
System.out.println(container.getInterestingSetup());
}
}
Run Code Online (Sandbox Code Playgroud)
也许,一个更简单的解决方案将包括使用某种方法,允许您在给定一堆字段及其相应值的情况下在 bean 中设置适当的信息InterestedSetup。您可以使用 Reflection API 来实现这一点。Apache Commons 类中的populate方法也BeansUtils很方便:
Map<String, Object> yamlConfig = yaml.load(yamlFile);
Object interestingObject = yamlConfig.get("interesting-setup");
Map<String, Object> interestingMap = (Map<String, Object>);
InterestingSetup finalObject = BeanUtils.populate(interestingMap);
Run Code Online (Sandbox Code Playgroud)
作为替代方法,您可以使用 Jackson 来处理 YAML 文件。代码将类似于:
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
// As the helper object Container doesn't contain all the properties
// it is necessary to indicate that fact to the library to avoid
// errors
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Container container = mapper.readValue(yamlString, Container.class);
System.out.println(container.getInterestingSetup());
Run Code Online (Sandbox Code Playgroud)
该类Container与上面提供的类相同,但添加了注释@JsonProperty以便成功处理该interesting-setup字段:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
// Instead of mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
// you can annotate the class with @JsonIgnoreProperties(ignoreUnknown = true)
// to avoid errors related to unknown properties
public class Container {
@JsonProperty("interesting-setup")
private InterestingSetup interestingSetup;
public InterestingSetup getInterestingSetup() {
return interestingSetup;
}
public void setInterestingSetup(InterestingSetup interestingSetup) {
this.interestingSetup = interestingSetup;
}
@Override
public String toString() {
return "Container{" +
"interestingSetup=" + interestingSetup +
'}';
}
}
Run Code Online (Sandbox Code Playgroud)
所需的工件可以从Maven下载,如下所示:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>2.13.1</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3096 次 |
| 最近记录: |