【问题标题】:How do I convert from YAML to JSON in Java?如何在 Java 中将 YAML 转换为 JSON?
【发布时间】: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 就很简单了。

标签: java json yaml


【解决方案1】:

感谢 HotLicks 提示(在问题 cmets 中)我终于以这种方式使用库 org.jsonSnakeYAML 实现了转换:

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 依赖项:&lt;dependencies&gt; &lt;dependency&gt; &lt;groupId&gt;org.json&lt;/groupId&gt; &lt;artifactId&gt;json&lt;/artifactId&gt; &lt;version&gt;20160810&lt;/version&gt; &lt;/dependency&gt; &lt;dependency&gt; &lt;groupId&gt;pl.droidsonroids.yaml&lt;/groupId&gt; &lt;artifactId&gt;snakeyaml&lt;/artifactId&gt; &lt;version&gt;1.18.2&lt;/version&gt; &lt;/dependency&gt; &lt;/dependencies&gt;
【解决方案2】:

非常感谢 Miguel A. Carrasco,他实际上已经解决了这个问题。但他的版本是限制性的。如果 root 是列表或原始值,他的代码将失败。最通用的解决方案是:

private static String convertToJson(String yamlString) {
    Yaml yaml= new Yaml();
    Object obj = yaml.load(yamlString);

    return JSONValue.toJSONString(obj);
}

【讨论】:

【解决方案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()
            )
        }
        
        
            
        

        【讨论】:

          猜你喜欢
          • 2015-08-02
          • 2016-12-11
          • 1970-01-01
          • 1970-01-01
          • 2017-08-16
          • 2018-10-28
          • 1970-01-01
          • 2019-04-18
          • 2016-02-16
          相关资源
          最近更新 更多