2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Java で JSON と YAML を変換する (Jackson と SnakeYAML を使って)

Last updated at Posted at 2020-10-09

概要

  • Java で JSON と YAML を変換する (Jackson と SnakeYAML を使って)
  • Jackson で JSON を Java オブジェクトに変換し、SnakeYAML で Java オブジェクトを YAML に変換する
  • SnakeYAML で YAML を Java オブジェクトに変換し、Jackson で Java オブジェクトを JSON に変換する
  • 環境: Java 15 (AdoptOpenJDK 15+36) + Jackson Databind 2.11.3 + ShakeYAML 1.27 + Gradle 6.6.1

Gradle によるビルド環境・実行環境を構築

以下の build.gradle を用意する。

plugins {
  id 'java'
}

repositories {
  mavenCentral()
}

dependencies {
  // Jackson Databind を使う
  implementation 'com.fasterxml.jackson.core:jackson-databind:2.11.3'

  // ShakeYAML を使う
  implementation 'org.yaml:snakeyaml:1.27'
}

// JsonToYaml クラスを実行するタスクを定義
task jsonToYaml(type: JavaExec) {
  main = 'JsonToYaml'
  classpath = sourceSets.main.runtimeClasspath
}

// YamlToJson クラスを実行するタスクを定義
task yamlToJson(type: JavaExec) {
  main = 'YamlToJson'
  classpath = sourceSets.main.runtimeClasspath
}

Java オブジェクトの中身を出力するクラスを用意

JSON や YAML を Java オブジェクトに変換した際のデータ構造やクラスについて把握するため、オブジェクトの情報を出力するクラスを用意する。

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * JSON や YAML 由来の Java オブジェクトの中身を出力する。
 */
public class ObjectDumper {

  private static final int INDENT = 2;

  public static String dump(Map<String, Object> obj) {
    List<String> buffer = new ArrayList<String>();
    dumpMap(obj, 0, buffer);
    return String.join("\n", buffer);
  }

  private static void dumpMap(Map<String, Object> obj, int depth, List<String> buffer) {
    for (Map.Entry<String, Object> entry : obj.entrySet()) {
      Object value = entry.getValue();
      if (value instanceof List) {
        buffer.add(line(entry.getKey(), value, depth));
        dumpList((List<Object>) value, depth + 1, buffer);
      } else if (value instanceof Map) {
        buffer.add(line(entry.getKey(), value, depth));
        dumpMap((Map<String, Object>) value, depth + 1, buffer);
      } else {
        buffer.add(line(entry.getKey(), value, depth));
      }
    }
  }

  private static void dumpList(List<Object> array, int depth, List<String> buffer) {
    for (Object element : array) {
      if (element instanceof List) {
        buffer.add(line(element, depth));
        dumpList((List<Object>) element, depth + 1, buffer);
      } else if (element instanceof Map) {
        buffer.add(line(element, depth));
        dumpMap((Map<String, Object>) element, depth + 1, buffer);
      } else {
        buffer.add(line(element, depth));
      }
    }
  }

  private static String line(String key, Object value, int depth) {
    if (value == null) {
      return " ".repeat(INDENT * depth) + key + ": " + "null";
    } else if (value instanceof Map) {
      return " ".repeat(INDENT * depth) + key + ": " + "(" + value.getClass().getName() + ")";
    } else if (value instanceof List) {
      return " ".repeat(INDENT * depth) + key + ": " + "(" + value.getClass().getName() + ")";
    } else {
      return " ".repeat(INDENT * depth) + key + ": " + value.toString() + " (" + value.getClass().getName() + ")";
    }
  }

  private static String line(Object value, int depth) {
    if (value == null) {
      return " ".repeat(INDENT * depth) + "null";
    } else if (value instanceof Map) {
      return " ".repeat(INDENT * depth) + "(" + value.getClass().getName() + ")";
    } else if (value instanceof List) {
      return " ".repeat(INDENT * depth) + "(" + value.getClass().getName() + ")";
    } else {
      return " ".repeat(INDENT * depth) + value.toString() + " (" + value.getClass().getName() + ")";
    }
  }
}

JSON を YAML に変換する

Jackson で変換: JSON → Java オブジェクト
SnakeYAML で変換: Java オブジェクト → YAML

ソースコード

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;

import java.util.Map;

public class JsonToYaml {

  public static void main(String[] args) throws JsonProcessingException {

    // JSON 文字列
    String json = """
      {
        "key": "value",
        "foo": "bar",
        "hoge": "fuga",
        "datalist": [
          {
            "string": "mojiretu",
            "integer": 123456,
            "decimal": 123.456,
            "boolean": true,
            "date": "2020-01-01",
            "timestamp": "2020-01-01T00:00:00.123456789+09:00",
            "nullonly": null,
            "object": {"hoge": "HOGE", "fuga": "FUGA"},
            "array": ["foo", "bar", "baz", ["spam", "ham", "eggs"]]
          },
          {
            "string": "文字列",
            "integer": 100000,
            "decimal": 999.999,
            "boolean": false,
            "date": "2020-01-01",
            "timestamp": "2020-01-01T00:00:00.123456789+09:00",
            "nullonly": null,
            "object": {"hoge": "ほげ", "fuga": "ふが"},
            "array": ["ふー", "ばー", "ばず", ["スパム", "ハム", "エッグ"]]
          }
        ]
      }
      """;
    System.out.println("********** 入力する JSON 文字列 **********");
    System.out.println(json);

    System.out.println("********** JSON を Java オブジェクト に変換 **********");
    ObjectMapper mapper = new ObjectMapper();
    Map<String, Object> obj = mapper.readValue(json, new TypeReference<Map<String, Object>>() {
    });
    System.out.println(ObjectDumper.dump(obj));

    System.out.println("********** Java オブジェクトを YAML に変換 **********");
    DumperOptions opts = new DumperOptions();
    opts.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
    String yaml = new Yaml(opts).dump(obj);
    System.out.println(yaml);
  }
}

実行結果

********** 入力する JSON 文字列 **********
{
  "key": "value",
  "foo": "bar",
  "hoge": "fuga",
  "datalist": [
    {
      "string": "mojiretu",
      "integer": 123456,
      "decimal": 123.456,
      "boolean": true,
      "date": "2020-01-01",
      "timestamp": "2020-01-01T00:00:00.123456789+09:00",
      "nullonly": null,
      "object": {"hoge": "HOGE", "fuga": "FUGA"},
      "array": ["foo", "bar", "baz", ["spam", "ham", "eggs"]]
    },
    {
      "string": "文字列",
      "integer": 100000,
      "decimal": 999.999,
      "boolean": false,
      "date": "2020-01-01",
      "timestamp": "2020-01-01T00:00:00.123456789+09:00",
      "nullonly": null,
      "object": {"hoge": "ほげ", "fuga": "ふが"},
      "array": ["ふー", "ばー", "ばず", ["スパム", "ハム", "エッグ"]]
    }
  ]
}

********** JSON を Java オブジェクト に変換 **********
key: value (java.lang.String)
foo: bar (java.lang.String)
hoge: fuga (java.lang.String)
datalist: (java.util.ArrayList)
  (java.util.LinkedHashMap)
    string: mojiretu (java.lang.String)
    integer: 123456 (java.lang.Integer)
    decimal: 123.456 (java.lang.Double)
    boolean: true (java.lang.Boolean)
    date: 2020-01-01 (java.lang.String)
    timestamp: 2020-01-01T00:00:00.123456789+09:00 (java.lang.String)
    nullonly: null
    object: (java.util.LinkedHashMap)
      hoge: HOGE (java.lang.String)
      fuga: FUGA (java.lang.String)
    array: (java.util.ArrayList)
      foo (java.lang.String)
      bar (java.lang.String)
      baz (java.lang.String)
      (java.util.ArrayList)
        spam (java.lang.String)
        ham (java.lang.String)
        eggs (java.lang.String)
  (java.util.LinkedHashMap)
    string: 文字列 (java.lang.String)
    integer: 100000 (java.lang.Integer)
    decimal: 999.999 (java.lang.Double)
    boolean: false (java.lang.Boolean)
    date: 2020-01-01 (java.lang.String)
    timestamp: 2020-01-01T00:00:00.123456789+09:00 (java.lang.String)
    nullonly: null
    object: (java.util.LinkedHashMap)
      hoge: ほげ (java.lang.String)
      fuga: ふが (java.lang.String)
    array: (java.util.ArrayList)
      ふー (java.lang.String)
      ばー (java.lang.String)
      ばず (java.lang.String)
      (java.util.ArrayList)
        スパム (java.lang.String)
        ハム (java.lang.String)
        エッグ (java.lang.String)
********** Java オブジェクトを YAML に変換 **********
key: value
foo: bar
hoge: fuga
datalist:
- string: mojiretu
  integer: 123456
  decimal: 123.456
  boolean: true
  date: '2020-01-01'
  timestamp: '2020-01-01T00:00:00.123456789+09:00'
  nullonly: null
  object:
    hoge: HOGE
    fuga: FUGA
  array:
  - foo
  - bar
  - baz
  - - spam
    - ham
    - eggs
- string: 文字列
  integer: 100000
  decimal: 999.999
  boolean: false
  date: '2020-01-01'
  timestamp: '2020-01-01T00:00:00.123456789+09:00'
  nullonly: null
  object:
    hoge: ほげ
    fuga: ふが
  array:
  - ふー
  - ばー
  - ばず
  - - スパム
    - ハム
    - エッグ

YAML を JSON に変換する

SnakeYAML で変換: YAML → Java オブジェクト
Jackson で変換: Java オブジェクト → JSON

ソースコード

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.yaml.snakeyaml.Yaml;

import java.util.Map;

public class YamlToJson {

  public static void main(String[] args) throws JsonProcessingException {

    // YAML 文字列
    String yaml = """
      key: value
      foo: bar
      hoge: fuga
      datalist:
      - string: mojiretu
        integer: 123456
        decimal: 123.456
        boolean: true
        date: 2020-01-01
        timestamp: 2020-01-01T00:00:00.123456789+09:00
        nullonly: null
        object:
          hoge: HOGE
          fuga: FUGA
        array:
        - foo
        - bar
        - baz
        - - spam
          - ham
          - eggs
      - string: 文字列
        integer: 100000
        decimal: 999.999
        boolean: false
        date: 2020-01-01
        timestamp: 2020-01-01T00:00:00.123456789+09:00
        nullonly: null
        object:
          hoge: ほげ
          fuga: ふが
        array:
        - ふー
        - ばー
        - ばず
        - - スパム
          - ハム
          - エッグ
      """;
    System.out.println("********** 入力する YAML 文字列 **********");
    System.out.println(yaml);

    System.out.println("********** YAML を Java オブジェクト に変換 **********");
    Map<String, Object> obj = new Yaml().load(yaml);
    System.out.println(ObjectDumper.dump(obj));

    System.out.println("********** Java オブジェクトを JSON に変換 **********");
    ObjectMapper mapper = new ObjectMapper();
    String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
    System.out.println(json);
  }
}

実行結果

********** 入力する YAML 文字列 **********
key: value
foo: bar
hoge: fuga
datalist:
- string: mojiretu
  integer: 123456
  decimal: 123.456
  boolean: true
  date: 2020-01-01
  timestamp: 2020-01-01T00:00:00.123456789+09:00
  nullonly: null
  object:
    hoge: HOGE
    fuga: FUGA
  array:
  - foo
  - bar
  - baz
  - - spam
    - ham
    - eggs
- string: 文字列
  integer: 100000
  decimal: 999.999
  boolean: false
  date: 2020-01-01
  timestamp: 2020-01-01T00:00:00.123456789+09:00
  nullonly: null
  object:
    hoge: ほげ
    fuga: ふが
  array:
  - ふー
  - ばー
  - ばず
  - - スパム
    - ハム
    - エッグ

********** YAML を Java オブジェクト に変換 **********
key: value (java.lang.String)
foo: bar (java.lang.String)
hoge: fuga (java.lang.String)
datalist: (java.util.ArrayList)
  (java.util.LinkedHashMap)
    string: mojiretu (java.lang.String)
    integer: 123456 (java.lang.Integer)
    decimal: 123.456 (java.lang.Double)
    boolean: true (java.lang.Boolean)
    date: Wed Jan 01 09:00:00 JST 2020 (java.util.Date)
    timestamp: Wed Jan 01 00:00:00 JST 2020 (java.util.Date)
    nullonly: null
    object: (java.util.LinkedHashMap)
      hoge: HOGE (java.lang.String)
      fuga: FUGA (java.lang.String)
    array: (java.util.ArrayList)
      foo (java.lang.String)
      bar (java.lang.String)
      baz (java.lang.String)
      (java.util.ArrayList)
        spam (java.lang.String)
        ham (java.lang.String)
        eggs (java.lang.String)
  (java.util.LinkedHashMap)
    string: 文字列 (java.lang.String)
    integer: 100000 (java.lang.Integer)
    decimal: 999.999 (java.lang.Double)
    boolean: false (java.lang.Boolean)
    date: Wed Jan 01 09:00:00 JST 2020 (java.util.Date)
    timestamp: Wed Jan 01 00:00:00 JST 2020 (java.util.Date)
    nullonly: null
    object: (java.util.LinkedHashMap)
      hoge: ほげ (java.lang.String)
      fuga: ふが (java.lang.String)
    array: (java.util.ArrayList)
      ふー (java.lang.String)
      ばー (java.lang.String)
      ばず (java.lang.String)
      (java.util.ArrayList)
        スパム (java.lang.String)
        ハム (java.lang.String)
        エッグ (java.lang.String)
********** Java オブジェクトを JSON に変換 **********
{
  "key" : "value",
  "foo" : "bar",
  "hoge" : "fuga",
  "datalist" : [ {
    "string" : "mojiretu",
    "integer" : 123456,
    "decimal" : 123.456,
    "boolean" : true,
    "date" : 1577836800000,
    "timestamp" : 1577804400123,
    "nullonly" : null,
    "object" : {
      "hoge" : "HOGE",
      "fuga" : "FUGA"
    },
    "array" : [ "foo", "bar", "baz", [ "spam", "ham", "eggs" ] ]
  }, {
    "string" : "文字列",
    "integer" : 100000,
    "decimal" : 999.999,
    "boolean" : false,
    "date" : 1577836800000,
    "timestamp" : 1577804400123,
    "nullonly" : null,
    "object" : {
      "hoge" : "ほげ",
      "fuga" : "ふが"
    },
    "array" : [ "ふー", "ばー", "ばず", [ "スパム", "ハム", "エッグ" ] ]
  } ]
}

参考資料

JSON + Jackson

YAML + SnakeYAML

2
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?