简体   繁体   English

如何在 Java 中从 YAML 转换为 JSON?

[英]How do I convert from YAML to JSON in Java?

I just want to convert a string that contains a yaml into another string that contains the corrseponding converted json using Java.我只想将包含 yaml 的字符串转换为另一个包含使用 Java 的 corrseponding 转换后的 json 的字符串。

For example supose that I have the content of this yaml例如假设我有这个 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

in a String called yamlDoc:在名为 yamlDoc 的字符串中:

String yamlDoc = "---\npaper:\n   uuid: 8a... etc...";

I want some method that can convert the yaml String into another String with the corresponding json, ie the following code我想要一些可以将yaml字符串转换为另一个带有相应json的字符串的方法,即以下代码

String yamlDoc = "---\npaper:\n   uuid: 8a... etc...";
String json = convertToJson(yamlDoc); // I want this method
System.out.println(json);

should print:应该打印:

{
    "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"
            }
        }
    ]
}

I want to know if exists something similar to the convertToJson() method in this example.我想知道在这个例子中是否存在类似于convertToJson()方法的东西。

I tried to achieve this using SnakeYAML , so this code我尝试使用SnakeYAML来实现这一点,所以这段代码

 Yaml yaml = new Yaml();
 Map<String,Object> map = (Map<String, Object>) yaml.load(yamlDoc);

constructs a map that contain the parsed YAML structure (using nested Maps).构造一个包含解析的 YAML 结构的映射(使用嵌套映射)。 Then if there is a parser that can convert a map into a json String it will solve my problem, but I didn't find something like that neither.然后,如果有一个解析器可以将地图转换为 json 字符串,它将解决我的问题,但我也没有找到类似的东西。

Any response will be greatly appreciated.任何回应将不胜感激。

Here is an implementation that uses Jackson:这是一个使用 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);
}

Requires:要求:

compile('com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.7.4')

Thanks to HotLicks tip (in the question comments) I finally achieve the conversion using the libraries org.json and SnakeYAML in this way:感谢 HotLicks 提示(在问题评论中)我终于以这种方式使用库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();
}

I don't know if it's the best way to do it, but it works for me.我不知道这是否是最好的方法,但它对我有用。

Big thanks to Miguel A. Carrasco he infact has solved the issue.非常感谢 Miguel A. Carrasco,他实际上已经解决了这个问题。 But his version is restrictive.但他的版本是有限制的。 His code fails if root is list or primitive value.如果 root 是列表或原始值,他的代码就会失败。 Most general solution is:最通用的解决方案是:

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

    return JSONValue.toJSONString(obj);
}

I found the example did not produce correct values when converting Swagger (OpenAPI) YAML to JSON.我发现该示例在将 Swagger (OpenAPI) YAML 转换为 JSON 时没有产生正确的值。 I wrote the following routine:我写了以下例程:

  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;
    }
  }

Then I could use SnakeYAML to load and output the JSON with the following:然后我可以使用 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));

I was directed to this question when searching for a solution to the same issue.在寻找同一问题的解决方案时,我被引导到了这个问题。

I also stumbled upon the following article https://dzone.com/articles/read-yaml-in-java-with-jackson我还偶然发现了以下文章https://dzone.com/articles/read-yaml-in-java-with-jackson

It seems Jackson JSON library has a YAML extension based upon SnakeYAML.似乎 Jackson JSON 库有一个基于 SnakeYAML 的 YAML 扩展。 As Jackson is one of the de facto libraries for JSON I thought that I should link this here.由于 Jackson 是事实上的 JSON 库之一,我认为我应该在这里链接它。

Thanks, Miguel!谢谢,米格尔! Your example helped a lot.你的例子很有帮助。 I didn't want to use the 'JSON-java' library.我不想使用“JSON-java”库。 I prefer GSON.我更喜欢 GSON。 But it wasn't hard to translate the logic from JSON-java over to GSON's domain model.但是将逻辑从 JSON-java 转换为 GSON 的域模型并不难。 A single function can do the trick:一个单一的功能可以做到这一点:

/**
 * 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));
}

Then you can parse a JsonElement from a YAML String with:然后,您可以使用以下命令从 YAML 字符串解析 JsonElement:

Yaml yaml = new Yaml();
Map<String, Object> yamlMap = yaml.load(yamlString);
JsonElement jsonElem = wrapSnakeObject(yamlMap);

and print it out with:并打印出来:

Gson gson = new GsonBuilder().setPrettyPrinting().create();
System.out.println(gson.toJson(jsonElem));

Using Gson:使用 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();

Spring boot with kotlin to return a yaml file content as json data Spring Boot 与 kotlin 将 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()
    )
}


    

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM