JSONのシリアライズとデシリアライズ
DataContractJsonSerializerを使うと、簡単にオブジェクトをJSONにシリアライズしたり、逆にJSONをデシリアライズしてオブジェクトにすることができます。
シリアライズ
次のようなメソッドを記述すれば、引数に渡したオブジェクトをJSONで表現した文字列が取得できます。DataContractJsonSerializerクラスを使用するにはSystem.Runtime.Serializationへ参照設定が必要ですのでご注意ください。
参照設定の方法については Visual Studioで参照設定を追加する方法 を参照して下さい。
Public Function Serialize(target As Object) As String
Using stream As New IO.MemoryStream
Dim serializer As New Runtime.Serialization.Json.DataContractJsonSerializer(target.GetType)
serializer.WriteObject(stream, target)
Dim result As String = System.Text.Encoding.UTF8.GetString(stream.ToArray())
Return result
End Using
End Function
■リスト1:VB版 オブジェクトをJSONにシリアライズするpublic string Serialize(object target)
{
using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
{
System.Runtime.Serialization.Json.DataContractJsonSerializer serializer
= new System.Runtime.Serialization.Json.DataContractJsonSerializer(target.GetType());
serializer.WriteObject(stream, target);
string result = System.Text.Encoding.UTF8.GetString(stream.ToArray());
return result;
}
}
■リスト2:C#版 オブジェクトをJSONにシリアライズする念のため使用例も紹介します。次のクラスを想定します。
Public Class Person
Public Property Name As String
Public Property Age As Integer
End Class
Public Class Parents
Public FamilyName As String
Public Father As Person
Public Mother As Person
End Class
■リスト3:このクラスに値を設定して、JSONにシリアライズするには次のようにします。
Dim parents As New Parents
parents.FamilyName = "フグ田"
parents.Father = New Person With {.Name = "フグ田マスオ", .Age = 28}
parents.Mother = New Person With {.Name = "フグ田サザエ", .Age = 24}
Dim json As String = Serialize(parents)
■リスト4:VB版 JSONへのシリアライズこの例を実行すると変数jsonの値は次のとおりになります。
{"FamilyName":"フグ田","Father":{"Age":28,"Name":"フグ田マスオ"},"Mother":{"Age":24,"Name":"フグ田サザエ"}}
■リスト5:生成されたJSONデシリアライズ1 DataContractJsonSerializer
DataContractJsonSerializerクラスを使ってデシリアライズする場合には、あらかじめそのJSONに合致する定義のクラスが必要です。つまり、未知のJSONをデシリアライズすることはできません。
未知のJSONをデシリアライズするにはJson.NETを使用します。この方法は後で説明します。
以下のメソッドはDataContractJsonSerializerクラスを使ってJSONをデシリアライズします。 型引数Tにはデシリアライズされるクラスまたは構造体を指定します。
Public Function Deserialize(Of T)(json As String) As T
Dim result As T
Dim serializer As New Runtime.Serialization.Json.DataContractJsonSerializer(GetType(T))
Using stream As New IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(json))
result = DirectCast(serializer.ReadObject(stream), T)
End Using
Return result
End Function
■リスト6:VB版 JSONをオブジェクトにデシリアライズするpublic T Deserialize<T>(string json)
{
T result;
System.Runtime.Serialization.Json.DataContractJsonSerializer serializer
= new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));
using (System.IO.MemoryStream stream
= new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(json)))
{
result = (T)serializer.ReadObject(stream);
}
return result;
}
■リスト7:C#版 JSONをオブジェクトにデシリアライズする念のため、このメソッドを呼び出す例も紹介します。シリアライズの例とおなじくParentsクラスとPersonクラスが存在する前提です。
Dim json As String = "{""FamilyName"":""フグ田"",""Father"":{""Age"":28,""Name"":""フグ田マスオ""},""Mother"":{""Age"":24,""Name"":""フグ田サザエ""}}"
Dim parents As Parents
parents = Deserialize(Of Parents)(json)
■リスト8:VB版 JSONからのデシリアライズこの例を実行するとparentsにはJSONで表現された値が設定されます。Parents, PersonとJSONの定義はVBまたはC#のクラスの定義とそれぞれ一致している必要があります。一致している保証がない場合、この手法は使用できません。その場合は、次に紹介するJson.NETの例を使用してください。
デシリアライズ2 Json.NET
Json.NETの準備
Json.NETを使ってJSONをデシリアライズすることもできます。Json.NETは非常にポピュラーなJSON操作用のライブラリでデシリアライズ以外にもいろいろな機能があります。
ASP.NETのプロジェクトの場合、既定でJson.NETが使用できるようになっています。その他の場合は、まずNuGetを使ってJson.NETをインストールする必要があります。
参照設定にNewtonsoft.Jsonが表示されていればJson.NETはすぐに利用可能です。 そうでない場合は、プロジェクトを右クリックして[NuGetパッケージの管理]から、Newtonsoft.Jsonを探してインストールしてください。 このライブラリは非常にメジャーなので、わざわざ検索しなくてもインストール可能なパッケージのトップに表示されているかもしれません。
C#の場合
C#の場合、Newtonsoft.Jsonの準備ができれば次のようにプログラムすれば未知のJSONをデシリアライズできます。
string json = "{\"FamilyName\":\"フグ田\",\"Father\":{\"Age\":28,\"Name\":\"フグ田マスオ\"},\"Mother\":{\"Age\":24,\"Name\":\"フグ田サザエ\"}}";
dynamic d = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
Console.WriteLine(d.FamilyName);
Console.WriteLine(d.Father.Name);
■リスト9:C#版 未知のJSONをデシリアライズする値を読み取るには、そのオブジェクトが既知であるかのようにプロパティ(のようなもの)にアクセスするだけです。
このように簡易的に未知の属性にアクセスできるのは動的ランタイムがうまく使われているからです。Json.NETはC#のdynamicととても相性がよいように作られています。
VBの場合
VBでも同様のことができるのですが、少し背景が異なります。Json.NETの作者は残念ながらVBとC#との動的ランタイムの背景の差を考慮に入れてくれなかったようです。そのためVBで同じことをするには少し手順が必要です。
まず、Option Strict を Offにする必要があります。これは必須です。
その上で、VB + Json.NETで単純にデシリアライズして値にアクセスするには次のようにします。
Dim json As String = "{""FamilyName"":""フグ田"",""Father"":{""Age"":28,""Name"":""フグ田マスオ""},""Mother"":{""Age"":24,""Name"":""フグ田サザエ""}}"
Dim d As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(json)
Console.WriteLine(d("FamilyName"))
Console.WriteLine(d("Father")("Name"))
■リスト10:VB版 未知のJSONをデシリアライズするJSONのデシリアライズについてはC#と同じですが、その後、デシリアライズした値を読み取るプログラムは少し見慣れないものになっています。
これで満足できるならば話は終わりです。どうしても d.FamilyName や d.Father.Name という記述で値にアクセスしたい場合はJson.NETの作者がやってくれなかったVB用の配慮を自分で行います。
それにはまず次のようなクラスを定義します。
Public Class DynamicAdapter
Inherits System.Dynamic.DynamicObject
Protected Property JSource As Newtonsoft.Json.Linq.JObject
Public Sub New(jsource As Newtonsoft.Json.Linq.JObject)
Me.JSource = jsource
End Sub
Public Overrides Function TryGetMember(binder As GetMemberBinder, ByRef result As Object) As Boolean
If JSource.ContainsKey(binder.Name) Then
Dim value As Object = JSource(binder.Name)
If TypeOf value Is Newtonsoft.Json.Linq.JObject Then
result = New DynamicAdapter(value)
Else
result = value
End If
Return True
Else
Return False
End If
End Function
End Class
■リスト11:VB版 .演算子で未知のJSONの属性にアクセスするアダプターこのクラスについてはここでは説明しません。興味がある人はDynamicObjectをキーワードに情報を調べてみてください。
このDynamicAdapterクラスが利用できる前提で、次のようにプログラムすることが可能になります。
Dim json As String = "{""FamilyName"":""フグ田"",""Father"":{""Age"":28,""Name"":""フグ田マスオ""},""Mother"":{""Age"":24,""Name"":""フグ田サザエ""}}"
Dim d As Object = New DynamicAdapter(Newtonsoft.Json.JsonConvert.DeserializeObject(json))
Console.WriteLine(d.FamilyName)
Console.WriteLine(d.Father.Name)
■リスト12:VB版 未知のJSONをデシリアライズして.でアクセスするバージョン
バージョン
Visual Basic 6.0 | 不可 |
Visual Basic.NET(2002) | 不可 |
Visual Basic.NET 2003 | 不可 |
Visual Basic 2005 | 不可 |
Visual Basic 2008 | 不可 |
Visual Basic 2010 | 不可。技術的にはOKですがこの記事では一部対応していないAPIを使用しています。 |
Visual Basic 2012 | OK |
Visual Basic 2013 | OK |
Visual Basic 2015 | OK |
Visual Basic 2017 | OK |