如何在 Java 中将 YAML 转换为 JSON?
Posted
技术标签:
【中文标题】如何在 Java 中将 YAML 转换为 JSON?【英文标题】:How do I convert from YAML to JSON in Java? 【发布时间】:2014-07-07 19:05:09 【问题描述】:我只想将一个包含 yaml 的字符串转换为另一个包含使用 Java 转换的对应 json 的字符串。
例如假设我有这个 yaml 的内容
---
paper:
uuid: 8a8cbf60-e067-11e3-8b68-0800200c9a66
name: On formally undecidable propositions of Principia Mathematica and related systems I.
author: Kurt Gödel.
tags:
- tag:
uuid: 98fb0d90-e067-11e3-8b68-0800200c9a66
name: Mathematics
- tag:
uuid: 3f25f680-e068-11e3-8b68-0800200c9a66
name: Logic
在名为 yamlDoc 的字符串中:
String yamlDoc = "---\npaper:\n uuid: 8a... etc...";
我想要一些可以将yaml字符串转换为另一个带有相应json的字符串的方法,即以下代码
String yamlDoc = "---\npaper:\n uuid: 8a... etc...";
String json = convertToJson(yamlDoc); // I want this method
System.out.println(json);
应该打印:
"paper":
"uuid": "8a8cbf60-e067-11e3-8b68-0800200c9a66",
"name": "On formally undecidable propositions of Principia Mathematica and related systems I.",
"author": "Kurt Gödel."
,
"tags": [
"tag":
"uuid": "98fb0d90-e067-11e3-8b68-0800200c9a66",
"name": "Mathematics"
,
"tag":
"uuid": "3f25f680-e068-11e3-8b68-0800200c9a66",
"name": "Logic"
]
我想知道在这个例子中是否存在类似于 convertToJson() 方法的东西。
我尝试使用SnakeYAML 来实现这一点,所以这段代码
Yaml yaml = new Yaml();
Map<String,Object> map = (Map<String, Object>) yaml.load(yamlDoc);
构造一个包含已解析 YAML 结构的映射(使用嵌套映射)。那么如果有一个解析器可以将地图转换为json字符串,它将解决我的问题,但我也没有找到类似的东西。
我们将不胜感激。
【问题讨论】:
使用 POJO 将允许您使用现有库,并且可能会自动执行。否则给自己一个 YAML 解析器,手动检查它,然后手动创建转换后的 JSON。 您在寻找什么?阅读您的帖子,我只能看到您不想做的事情。你准备做什么?抱歉,-1 因为没有显示任何解决此问题的尝试。我看到的都是我的问题,请帮我解决。 我知道Jackson can read and write YAML。也许使用new ObjectMapper(new YAMLFactory())
将 YAML 读入映射结构,然后使用 new ObjectMapper()
编写 JSON?
感谢superEb的建议,不知道Jackson会读YAMLs
肯定有一些工具可以将 YAML 转换为地图和列表。一旦如此转换,生成相应的 JSON 就很简单了。
【参考方案1】:
感谢 HotLicks 提示(在问题 cmets 中)我终于以这种方式使用库 org.json 和 SnakeYAML 实现了转换:
private static String convertToJson(String yamlString)
Yaml yaml= new Yaml();
Map<String,Object> map= (Map<String, Object>) yaml.load(yamlString);
JSONObject jsonObject=new JSONObject(map);
return jsonObject.toString();
我不知道这是否是最好的方法,但它对我有用。
【讨论】:
由于第 3 行的未经检查的强制转换,这不起作用。每次都会抛出 ClassCastException。 org.json 链接已损坏,但这里是获取库的 maven 依赖项:<dependencies> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20160810</version> </dependency> <dependency> <groupId>pl.droidsonroids.yaml</groupId> <artifactId>snakeyaml</artifactId> <version>1.18.2</version> </dependency> </dependencies>
【参考方案2】:
非常感谢 Miguel A. Carrasco,他实际上已经解决了这个问题。但他的版本是限制性的。如果 root 是列表或原始值,他的代码将失败。最通用的解决方案是:
private static String convertToJson(String yamlString)
Yaml yaml= new Yaml();
Object obj = yaml.load(yamlString);
return JSONValue.toJSONString(obj);
【讨论】:
JSONValue 从何而来? 我相信他们使用的是 json-simple (javadoc: alex-public-doc.s3.amazonaws.com/json_simple-1.1/index.html),但该项目几乎被放弃了。核心 javax 包将是要走的路。(docs.oracle.com/javaee/7/api/javax/json/JsonValue.html) 使用 javax.json 会将方法从 JSONValue.ToJsonString 更改为 JsonValue.toString【参考方案3】:这是一个使用 Jackson 的实现:
String convertYamlToJson(String yaml)
ObjectMapper yamlReader = new ObjectMapper(new YAMLFactory());
Object obj = yamlReader.readValue(yaml, Object.class);
ObjectMapper jsonWriter = new ObjectMapper();
return jsonWriter.writeValueAsString(obj);
要求:
compile('com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.7.4')
【讨论】:
最佳答案,因为它只依赖于 Jackson,而不是两个不同的库。 对我有用的是:ObjectMapper yamlReader = new ObjectMapper(new YAMLFactory()); Object obj = yamlReader.readValue(new File("src/main/resources/file.yaml"), Object.class); ObjectMapper jsonWriter = new ObjectMapper(); String json = jsonWriter.writeValueAsString(obj); System.out.println(json);
这对我不起作用,当我们有一个数组时它是覆盖元素【参考方案4】:
我发现该示例在将 Swagger (OpenAPI) YAML 转换为 JSON 时没有生成正确的值。我写了如下例程:
private static Object _convertToJson(Object o) throws JSONException
if (o instanceof Map)
Map<Object, Object> map = (Map<Object, Object>) o;
JSONObject result = new JSONObject();
for (Map.Entry<Object, Object> stringObjectEntry : map.entrySet())
String key = stringObjectEntry.getKey().toString();
result.put(key, _convertToJson(stringObjectEntry.getValue()));
return result;
else if (o instanceof ArrayList)
ArrayList arrayList = (ArrayList) o;
JSONArray result = new JSONArray();
for (Object arrayObject : arrayList)
result.put(_convertToJson(arrayObject));
return result;
else if (o instanceof String)
return o;
else if (o instanceof Boolean)
return o;
else
log.error("Unsupported class [0]", o.getClass().getName());
return o;
然后我可以使用 SnakeYAML 来加载和输出 JSON:
Yaml yaml= new Yaml();
Map<String,Object> map= (Map<String, Object>) yaml.load(yamlString);
JSONObject jsonObject = (JSONObject) _convertToJson(map);
System.out.println(jsonObject.toString(2));
【讨论】:
【参考方案5】:在寻找同一问题的解决方案时,我被定向到了这个问题。
我还偶然发现了以下文章https://dzone.com/articles/read-yaml-in-java-with-jackson
Jackson JSON 库似乎有一个基于 SnakeYAML 的 YAML 扩展。 由于 Jackson 是事实上的 JSON 库之一,我认为我应该在这里链接它。
【讨论】:
【参考方案6】:谢谢,米格尔!你的例子帮助很大。我不想使用“JSON-java”库。我更喜欢GSON。但是将逻辑从 JSON-java 转换为 GSON 的域模型并不难。一个函数就可以解决问题:
/**
* Wraps the object returned by the Snake YAML parser into a GSON JsonElement
* representation. This is similar to the logic in the wrap() function of:
*
* https://github.com/stleary/JSON-java/blob/master/JSONObject.java
*/
public static JsonElement wrapSnakeObject(Object o)
//NULL => JsonNull
if (o == null)
return JsonNull.INSTANCE;
// Collection => JsonArray
if (o instanceof Collection)
JsonArray array = new JsonArray();
for (Object childObj : (Collection<?>)o)
array.add(wrapSnakeObject(childObj));
return array;
// Array => JsonArray
if (o.getClass().isArray())
JsonArray array = new JsonArray();
int length = Array.getLength(array);
for (int i=0; i<length; i++)
array.add(wrapSnakeObject(Array.get(array, i)));
return array;
// Map => JsonObject
if (o instanceof Map)
Map<?, ?> map = (Map<?, ?>)o;
JsonObject jsonObject = new JsonObject();
for (final Map.Entry<?, ?> entry : map.entrySet())
final String name = String.valueOf(entry.getKey());
final Object value = entry.getValue();
jsonObject.add(name, wrapSnakeObject(value));
return jsonObject;
// everything else => JsonPrimitive
if (o instanceof String)
return new JsonPrimitive((String)o);
if (o instanceof Number)
return new JsonPrimitive((Number)o);
if (o instanceof Character)
return new JsonPrimitive((Character)o);
if (o instanceof Boolean)
return new JsonPrimitive((Boolean)o);
// otherwise.. string is a good guess
return new JsonPrimitive(String.valueOf(o));
然后您可以使用以下命令从 YAML 字符串中解析 JsonElement:
Yaml yaml = new Yaml();
Map<String, Object> yamlMap = yaml.load(yamlString);
JsonElement jsonElem = wrapSnakeObject(yamlMap);
然后打印出来:
Gson gson = new GsonBuilder().setPrettyPrinting().create();
System.out.println(gson.toJson(jsonElem));
【讨论】:
这太复杂了,使用 Gson 可以简单得多。【参考方案7】:使用 Gson:
var yaml = new YAML();
var gson = new Gson();
var reader = new FileReader(path.toFile());
var obj = yaml.load(reader);
var writer = new StringWriter();
gson.toJson(obj, writer);
String result = writer.toString();
【讨论】:
【参考方案8】:使用 kotlin 进行 Spring Boot 以将 yaml 文件内容作为 json 数据返回
package br.com.sportplace.controller
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import java.io.InputStream
@RestController
@RequestMapping(value = ["resources/docs"])
class DocsController
@GetMapping(produces = ["application/json"])
fun load(): ResponseEntity<Any>
return getResourceFileAsString()
fun getResourceFileAsString(): ResponseEntity<Any>
val inputStream = getResourceFileAsInputStream("openapi/api.yaml")
return if (inputStream != null)
val objectMapper = ObjectMapper(YAMLFactory())
ResponseEntity.ok(objectMapper.readValue(inputStream, Any::class.java))
else
ResponseEntity(ErrorResponse(), HttpStatus.INTERNAL_SERVER_ERROR)
fun getResourceFileAsInputStream(fileName: String?): InputStream?
val classLoader = DocsController::class.java.classLoader
return classLoader.getResourceAsStream(fileName)
private data class ErrorResponse(
val message: String = "Failed to load resource file",
val success: Boolean = false,
val timestamp: Long = System.currentTimeMillis()
)
【讨论】:
以上是关于如何在 Java 中将 YAML 转换为 JSON?的主要内容,如果未能解决你的问题,请参考以下文章
YamlDotNet 在 C# 中将 YAML 转换为 JSON
如何在 Retrofit 库中将 YAML 响应正文解析为 POJO?