[Swift3] JSON文字列の作成

1 はじめに

今回は、JSON文字列をSwiftで作成する要領について纏めてみました。

本記事は、例えば、「APIで下記のようなJSONデータとしてPOSTしたい!」というような場合に、プログラムで、このJSON文字列を生成する事になりますが、「う、どうだっけ・・・」とちょっと固まりそうな方(私のことです)に向けたものです。

{
    "Identifire": "123456",
    "Code": "AAA-ZZZ",
    "LastUpdate": "2017-04-01T09:30:00.000Z",
    "Tags": [
        {
            "Value": "Taro",
            "Key": "Name"
        },
        {
            "Value": 23,
            "Key": "Age"
        }
    ]
}

なお、JSONについては、下記がとっても優しく分かりやすかったので、超おすすめです。
非エンジニアに贈る「具体例でさらっと学ぶJSON」

2 JSONSerialization

Swiftでは、Foundationのオブジェクトで表現された データをJSONSerializationでJSONオブジェクト(Data)に変換し、更にStringに変換することでJSON文字列を生成することができます。

let jsonObj = ["Name":"Taro"]

do {
    let jsonData = try JSONSerialization.data(withJSONObject: jsonObj, options: [])
    let jsonStr = String(bytes: jsonData, encoding: .utf8)!
    print(jsonStr)  // 生成されたJSON文字列 => {"Name":"Taro"}
} catch let error {
    print(error)
}

JSONSerializationを使用した変換は、定形作業なので、問題は、各種のJSONをFoundationオブジェクトで表現するところだと思います。

3 Dictionary

最初に、最も簡単(?)なJSON文字列を生成してみます。

{
    "Name":"Taro"
}

Swiftでのコードは、次のようになります。

let jsonObj = ["Name":"Taro"]

動的に作成するなら、下記のようになるでしょうか。

var jsonObj = Dictionary<String,Any>()
jsonObj["Name"] = "Taro"

JSONにおけるオブジェクト型データ(Key、Value)は、Foundationでは、Dictionaryで表現します。キーは、String 一択ですが、値の方は、色々考えられますので、Anyとしています。(例えば、全部の値が文字列であるならDictionary<String,String>のように定義することも可能です)

var jsonObj = Dictionary<String,Any>()
jsonObj["Name"] = "Taro"
jsonObj["Age"] = 23 // Anyなので数値も入ります

/*
{
    "Name":"Taro",
    "Age":23
}
*/

4 Array

複数の要素を保持するものには、先のDictionaryの他に、Arrayがあります。

let jsonObj: [Any] = ["Name",123] 

/*
[
    "Name", 
    123
]
*/

同じく動的に生成するなら、次のようになります。

var jsonObj = Array<Any>()
jsonObj.append("Name")
jsonObj.append(123)
/*
[
    "Name", 
    123
]
*/

Arrayに含まれる要素は、一種類でない場合、Anyとするしか無いでしょう。

5 階層構造

複数の要素を保持できるDictionaryや、Arrayを値として指定した場合、階層構造を築くことになります。

下記は、Arrayの要素に、Dictionaryを設定している例です。

var jsonObj = Array<Any>()
jsonObj.append(["Name":"Taro"])
jsonObj.append(["Name":"Hanako"])
/*
[
    {
        "Name": "Taro"
    }, 
    {
        "Name": "Hanako"
    }
]
*/

さて、それでは、次のようなJSONは、プログラムで生成する場合、どうやって作業を進めれば良いのでしょう?

{
    "person": {
        "Age": 23, 
        "Name": "Taro"
    }
}

最初にトップレベルの型ですが、全体が、{ } で囲まれているので、トップレベルはDictionaryであると言えます。( [ ] の場合は、Arrayです)

そして、その1つ目の要素(上の例では、要素は1つしかありません)は、キーが "person" で、値 が「 ”{ Dictionary }” 」です。

こういう場合は、最初に personを作成します。

var person = Dictionary<String,Any>()
person["Name"] = "Taro"
person["Age"] = 23

そして、このpersonをトップレベルのオブジェクトの要素として追加します。

var jsonObj = Dictionary<String,Any>()
jsonObj["person"] = person

どんなに、階層構造になっていても、一番下のオブジェクトから順に生成して、上の要素に追加して行けばOKです。

6 練習

それでは、最初に例として紹介したJSON文字列を、Swiftで書いてみます。

眺めてみると・・・まず、トップオブジェクトはDictionaryです。 その要素は4つであり、最後の要素の値は、Arrayのようです。 また、Arrayの要素は2つであり、それぞれDictionaryです。

{
    "Identifire": "123456",
    "Code": "AAA-ZZZ",
    "LastUpdate": "2017-04-01T09:30:00.000Z",
    "Tags": [
        {
            "Value": "Taro",
            "Key": "Name"
        },
        {
            "Value": 23,
            "Key": "Age"
        }
    ]
}

コードは、以下のとおりです。

// Dictionary(Tags配列の要素)を生成する
var name = Dictionary<String, String>() //  var name = Dictionary<String, Any>() でもよい
name["Key"] = "Name"
name["Value"] = "Taro"

// Dictionary(Tags配列の要素)を生成する
var age = Dictionary<String, Any>()
age["Key"] = "Age"
age["Value"] = 23

// Tags配列の生成
var tags = Array<Any>() // var tags = Array<Dictionary<String,  Any>>() でもよい

// Tags配列へ要素を追加する
tags.append(name)
tags.append(age)

// トップオブジェクトの生成
var jsonObj = Dictionary<String, Any>()

// トップオブジェクトへ要素を追加する
jsonObj["Identifire"] = "123456"
jsonObj["Code"] = "AAA-ZZZ"
jsonObj["LastUpdate"] = "2017-04-01T09:30:00.000Z"
jsonObj["Tags"] = tags

7 最後に

ちょっと慣れてきたでしょうか。(と自分に言い聞かせています)

8 参考リンク

API Reference JSONSerialization
非エンジニアに贈る「具体例でさらっと学ぶJSON」