web-dev-qa-db-ja.com

JavaでYAMLからJSONに変換するにはどうすればよいですか?

Javaを使用して、yamlを含む文字列を、対応する変換された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文字列に変換できるパーサーがあれば、私の問題は解決しますが、そのようなものも見つかりませんでした。

どんな反応も大歓迎です。

19

ジャクソンを使用した実装は次のとおりです。

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')
38
Cory Klein

HotLicksのヒント(質問のコメント)のおかげで、ようやく 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();
}

それが最善の方法であるかどうかはわかりませんが、私にとってはうまくいきます。

10

彼が実際に問題を解決したミゲルA.カラスコに大いに感謝します。しかし、彼のバージョンには制限があります。ルートがリストまたはプリミティブ値である場合、彼のコードは失敗します。最も一般的な解決策は次のとおりです。

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

    return JSONValue.toJSONString(obj);
}
3
Todor Kisov

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));
1
JonathanT

ありがとう、ミゲル!あなたの例は大いに役立ちました。 「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));
1
Dan R.

同じ問題の解決策を探すときに、私はこの質問に導かれました。

また、次の記事につまずきました https://dzone.com/articles/read-yaml-in-Java-with-jackson

Jackson JSONライブラリにはSnakeYAMLに基づくYAML拡張機能があるようです。ジャクソンはJSONの事実上のライブラリの1つであるため、ここにリンクする必要があると考えました。

1
MarkAddison