Jackson 将 YAML 文件反序列化为 Map(没有自定义反序列化器)
Posted
技术标签:
【中文标题】Jackson 将 YAML 文件反序列化为 Map(没有自定义反序列化器)【英文标题】:Jackson deserialization of YAML file into Map (with no custom deserializer) 【发布时间】:2019-02-08 17:17:23 【问题描述】:我正在尝试将 YAML 文件加载到 Map
的实例中。有没有办法在不定义自定义反序列化器的情况下加载它(例如使用注释?)?
这是我的 YAML 文件的示例:
- site: First Site
url: some_url
username: some_name
password: some_password
- site: Second Site
url: its_url
username: its_name
password: its_password
这是将一个“站点配置”反序列化为(由http://www.jsonschema2pojo.org/ 生成)的 java bean 类:
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import org.apache.commons.lang3.builder.ToStringBuilder;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder(
"site",
"url",
"username",
"password"
)
public class SiteConfiguration
@JsonProperty("site")
private String site;
@JsonProperty("url")
private String url;
@JsonProperty("username")
private String username;
@JsonProperty("password")
private String password;
/**
* No args constructor for use in serialization
*
*/
public SiteConfiguration()
/**
*
* @param site
* @param username
* @param password
* @param url
*/
public SiteConfiguration(String site, String url, String username, String password)
super();
this.site = site;
this.url = url;
this.username = username;
this.password = password;
@JsonProperty("site")
public String getSite()
return site;
@JsonProperty("site")
public void setSite(String site)
this.site = site;
@JsonProperty("url")
public String getUrl()
return url;
@JsonProperty("url")
public void setUrl(String url)
this.url = url;
@JsonProperty("username")
public String getUsername()
return username;
@JsonProperty("username")
public void setUsername(String username)
this.username = username;
@JsonProperty("password")
public String getPassword()
return password;
@JsonProperty("password")
public void setPassword(String password)
this.password = password;
@Override
public String toString()
return new ToStringBuilder(this).append("site", site).append("url", url).append("username", username).append("password", password).toString();
最后,这是将上面的 YAML 反序列化为 Map
的代码。
private static Map<String,SiteConfiguration> sites;
public static SiteConfiguration getSiteConfiguration(String key)
if (sites == null)
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
try
// todo this finishes on: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.LinkedHashMap` out of START_ARRAY token
// sites = mapper.readValue(YamlReader.class.getClass().getResource("/site-configuration.yaml"), new TypeReference<Map<String,SiteConfiguration>>() );
SiteConfiguration[] sitesArray = mapper.readValue(YamlReader.class.getClass().getResource("/site-configuration.yaml"), SiteConfiguration[].class);
sites = new HashMap<>();
for (SiteConfiguration site : sitesArray) //todo is there Jackson built-in deserialization?
sites.put(site.getSite(), site);
catch (Exception e)
throw new RuntimeException(e);
return sites.get(key);
如您所见,我分两步完成。首先我将文件反序列化为SiteConfiguration
实例的数组,然后将它们放入Map
其中site
字段代表映射键。
有没有办法在省略SiteConfiguration
实例的数组时做同样的事情?是使用自定义反序列化器的唯一方法吗?
【问题讨论】:
【参考方案1】:更改 YAML 的结构。如果要将数据反序列化为地图,则需要在 YAML 文件中以地图的形式开始。您的示例中有一系列映射,但您需要映射的映射。
https://yaml.org/spec/1.2/spec.html#id2759963
示例 2.4。映射序列 (球员统计)
- name: Mark McGwire hr: 65 avg: 0.278 - name: Sammy Sosa hr: 63 avg: 0.288
示例 10.1。 !!地图示例
Block style: !!map Clark : Evans Ingy : döt Net Oren : Ben-Kiki
试试这个:
First Site:
site: First Site
url: some_url
username: some_name
password: some_password
Second Site:
site: Second Site
url: its_url
username: its_name
password: its_password
此结构适用于没有自定义反序列化器的 Jackson 2.9.9。
【讨论】:
以上是关于Jackson 将 YAML 文件反序列化为 Map(没有自定义反序列化器)的主要内容,如果未能解决你的问题,请参考以下文章