手元に作りかけの個人プロジェクトがあり、D言語でJSON-RPCサーバっぽいものを作ろうとしていた形跡があります。どうやら2年前くらいに作ろうとしていたもののようです。
そういえば、2年くらい前にD言語を勉強しようとして、うやむやになっていたような記憶があります。。
というわけで、改めてD言語を勉強していけたらいいなあ、と思ってコードを触り始めたものの、
ただ JSON を扱うだけでも一苦労してるので整理します🥺
JSONのパース
const jsonstr = `{
"x": 10,
"y": 20.5,
"enabled": true,
"message": "hoge",
"items": ["a", "b", "c"],
"detail": { "image": null }
}`;
JSONValue json = parseJSON(jsonstr);
writeln(json);
parseJSON を使うことで、文字列から JSONValue を得ることができます。
writeln に JSONValue を渡すと普通にJSON形式で出力されます。(JSONValue.toString() の内部で toJSON を呼んでいるらしいです)
JSONValueへのアクセス
writeln("x: ", json["x"].get!int);
writeln("x: ", json["x"].integer);
writeln("y: ", json["y"].get!double);
writeln("y: ", json["y"].floating);
writeln(json["items"][1]);
get(T)() で値を指定した型で取得できます。
また、それぞれの型で取得するためのプロパティもあります。(integer(), floating() など)
適切なプロパティでアクセスしないと JSONException が発生します。
objectの内の配列にアクセスする場合は添字を使います。
JSONValueへの値の設定
json["new"] = "value";
json["number"] = 1000;
json["fuga"] = [1,2,3];
json["piyo"] = ["first":1,"second":2];
writeln(json);
そのまま代入するとそれぞれの値として設定できました。
JSONValueの値の型
writeln(json["items"].type);
writeln(json["itens"].type == JSONType.array);
type() プロパティで JSONType を返します。
JSONValueの作成
JSONValue newJson = JSONValue();
newJson["foo"] = 0;
newJson["baz"] = "a";
newJson["bar"] = null;
writeln(newJson);
JSONValueを作った後に値を設定することで実現できます。
// これは連想配列の値の型がバラバラなのでエラーになる
newJson = JSONValue([
"foo": 0,
"baz": "a",
"bar": null
]);
writeln(newJson);
JSONValue作成時に連想配列を渡すことで相当する値を作成することもできるのですが、
上記のように推論できない連想配列型の場合はエラーになります。たとえば string[string] でよければ作れます。
JSON文字列への変換
writeln(toJSON(json))
writeln(toJSON(json, true));
toJSON() で文字列に変換できます。
toJSON の第二引数(pretty)に true を指定すると、改行やインデントをした綺麗なJSON文字列が返ります。
JSON から struct への変換
import asdf;
struct Point {
int x;
int y;
}
const pointJson = `{"x": 100, "y": 200}`;
const point = pointJson.deserialize!Point;
writeln(point);
JSONValue から struct へのマッピング(Go言語の Unmarshal 相当)は std.json にはないようです。
asdf というライブラリの deserialize(T)() でjson文字列からstructへの変換は実現できました。