C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[7]: JSON(入れ子)のデシリアライズ


(過去ログ 135 を表示中)

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■79705 / inTopicNo.1)  JSON(入れ子)のデシリアライズ
  
□投稿者/ やんまー (1回)-(2016/05/08(Sun) 01:58:25)

分類:[VB.NET/VB2005 以降] 

2016/05/08(Sun) 01:59:10 編集(投稿者)

畏れ入ります。

JSON解析をしようと思ったのですが、いきなり躓いてしまいました。

まずはこちら
http://homepage1.nifty.com/rucio/main/VBdotNet/Samples201/Sample234DataContractJsonSerializer.htm
2.JSONをデシリアライズする例

を試してみました。

これは実行できたのですが、少しいじってみたらもうわからなくなりました。
わからなくなったのは、入れ子、になっているパターンはどう読み込むのか、というところです。

サンプルでは
{
"Id":627,
"Name":"徳川家康"
}

な感じなのですが、例えば以下のように入れ子になった場合にはどうすればよいのでしょうか?

{"Id":[
{
"ID1":111,
"ID2":222
}
],

"Name":"徳川家康"
}

Personクラスを何か修正しなければいけないかと思いますが・・・


http://future-convergence.hatenablog.jp/entry/2015/01/07/001045
のやり方が良さそうだとも思ったのですが、Json.NETをインストールせねばならず、
できれば新たに何かをインストールしないでやりたいです。
引用返信 編集キー/
■79707 / inTopicNo.2)  Re[1]: JSON(入れ子)のデシリアライズ
□投稿者/ WebSurfer (907回)-(2016/05/08(Sun) 08:15:08)
No79705 (やんまー さん) に返信
> Personクラスを何か修正しなければいけないかと思いますが・・・
>

修正すると言うよりも、最初に JSON 文字列ありきではなく、プログラムで扱うのは
オブジェクト (Person クラス) なのですから、オブジェクトの定義をまず最初に考えると
言うことになると思います。
引用返信 編集キー/
■79709 / inTopicNo.3)  Re[2]: JSON(入れ子)のデシリアライズ
□投稿者/ やんまー (2回)-(2016/05/08(Sun) 11:02:56)
WebSurfer様

> 修正すると言うよりも、最初に JSON 文字列ありきではなく、プログラムで扱うのは
> オブジェクト (Person クラス) なのですから、オブジェクトの定義をまず最初に考えると
> 言うことになると思います。

書き込みありがとうございます!

そうですよね。

もともとの定義が integer だったので
これを配列・・・?いやハッシュにすればいいのでしょうか・・・。

要素の中に更にキーが有る状態をどう表現したら良いのか・・・。

強引に正規表現でやろうかと思っていたのですが、せっかく機能があるようですので
できたらこれを拡張して利用するのはどうしたら良いかが気になりました。

もう少しヒントよろしくお願いいたします 汗



No79707 (WebSurfer さん) に返信
> ■No79705 (やんまー さん) に返信
>>Personクラスを何か修正しなければいけないかと思いますが・・・
> >
>

引用返信 編集キー/
■79711 / inTopicNo.4)  Re[3]: JSON(入れ子)のデシリアライズ
□投稿者/ WebSurfer (908回)-(2016/05/08(Sun) 12:26:09)
No79709 (やんまー さん) に返信

[{"ID1":111,"ID2":222}] が何を意味するか分かりますか?

ID1, ID2 というメンバーを持つオブジェクトの配列ですよね。(この例では配列の要素
数は 1 ですが)

とすると、そのオブジェクトのクラス定義を追加し(仮に ChildID クラスとします)、
親の Person クラスの Id は追加したクラス定義の List(Of ChildID) を指すように定義
し直せばいいと思います。

具体的には以下のような感じ:

Option Strict On
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Json
Imports System.Collections.Generic
Imports System.IO
Imports System.Text

Module Module1

    Sub Main()
        Dim p As New Person
        p.Name = "徳川家康"
        p.Id = New List(Of ChildId)
        p.Id.Add(New ChildId With {.ID1 = 111, .ID2 = 222})

        Dim json As String

        Using stream As New MemoryStream
            Dim serializer As New DataContractJsonSerializer(p.GetType)
            serializer.WriteObject(stream, p)
            stream.Position = 0

            Using reader As New StreamReader(stream)
                json = reader.ReadToEnd
                Console.WriteLine(json)
            End Using
        End Using

        Console.WriteLine("---------------------------------------------------")

        Using stream As New MemoryStream(Encoding.Unicode.GetBytes(json))
            Dim serializer As New DataContractJsonSerializer(p.GetType)
            Dim p2 As Person = DirectCast(serializer.ReadObject(stream), Person)
            Console.WriteLine("Name: {0}", p2.Name)
            For Each childId As ChildId In p2.Id
                Console.WriteLine("ID1: {0}, ID2: {1}", childId.ID1, childId.ID2)
            Next
        End Using
    End Sub

    ' 結果は:
    ' {"Id":[{"ID1":111,"ID2":222}],"Name":"徳川家康"}
    ' ---------------------------------------------------
    ' Name: 徳川家康
    ' ID1: 111, ID2: 222

End Module

<DataContract()>
Public Class Person
    <DataMember()>
    Public Property Id As List(Of ChildId)

    <DataMember()>
    Public Property Name As String
End Class

<DataContract()>
Public Class ChildId
    <DataMember()>
    Public Property ID1 As Integer

    <DataMember()>
    Public Property ID2 As Integer
End Class

引用返信 編集キー/
■79712 / inTopicNo.5)  Re[4]: JSON(入れ子)のデシリアライズ
□投稿者/ やんまー (3回)-(2016/05/08(Sun) 14:20:32)
WebSurfer 様

とってもご丁寧にありがとうございます!やりたいことが出来ました!!

配列というとstring()かな・・・と思ってしまってハマってしましました。Listを使えばよかったのですね。。。


実はまた一つ疑問がでてしまったのですが、
<DataContract()>
<DataMember()>
は別に付けなくてもコンパイルは通り、実行結果も同じでした。

これはなんのために必要なのでしょうか・・・
WEB検索してみましても、大抵はつけてありました。
件のVISUAL BASIC中学生 のページには使ってありませんでしたので、
無くてもいいのになんで必要?となってしまいました。

WCFで必要・・?ということでしょうか・・・。
http://blogs.wankuma.com/kazuki/archive/2008/12/21/164599.aspx

WCFがわからなかったのですが、そのWCFというサービスを使わないのなら不要なのでしょうか・・・。






No79711 (WebSurfer さん) に返信
> ■No79709 (やんまー さん) に返信

引用返信 編集キー/
■79713 / inTopicNo.6)  Re[5]: JSON(入れ子)のデシリアライズ
□投稿者/ WebSurfer (909回)-(2016/05/08(Sun) 15:38:02)
No79712 (やんまー さん) に返信

> WCFがわからなかったのですが、そのWCFというサービスを使わないのなら不要なのでしょうか・・・。

そういうわけではなく、DataContractJsonSerializer を使って JSON と .NET オブジェクト
の間のシリアル化 / 逆シリアル化を行う際には DataContractAttribute, DataMemberAttribute
を付与するのが Microsoft の推奨ということです。

具体例は以下の記事を見てください。

方法 : JSON データをシリアル化および逆シリアル化する
https://msdn.microsoft.com/ja-jp/library/bb412179(v=vs.110).aspx

理由は、上の記事からリンクが張られている「サービス コントラクトの設計」や
「DataContractAttribute」の記事を見るといろいろ書いてあります。

自分は以下が主な理由だと理解しています。

"最大限の相互運用性を実現するために、使用する型を DataContractAttribute 属性と
DataMemberAttribute 属性でマークして、データ コントラクトを作成することをお勧めします。"

"DataContractAttribute の適用によって、DataContractSerializer によるデータのシリアル化
と逆シリアル化を明示的に有効にします。"(DataContractJsonSerializer も含む)
引用返信 編集キー/
■79714 / inTopicNo.7)  Re[6]: JSON(入れ子)のデシリアライズ
□投稿者/ やんまー (4回)-(2016/05/08(Sun) 15:53:49)
WebSurfer様

ありがとうございます。

つけなくともなんとなく動いてしまうけど、つけたほうが安全、ということですかね・・・。

つけておかないと思わぬ不具合があるかもしれないよ、といったところでしょうか。


本当にありがとうございました。すごく助かりました!
解決済み
引用返信 編集キー/
■79722 / inTopicNo.8)  Re[7]: JSON(入れ子)のデシリアライズ
□投稿者/ WebSurfer (911回)-(2016/05/09(Mon) 13:06:48)
No79714 (やんまー さん) に返信

> つけなくともなんとなく動いてしまうけど、つけたほうが安全、ということですかね・・・。

そういうレベルではなくて、必ずつけましょうと言うレベルに近いと自分は思っていますが。

DataContractJsonSerializer(DataContract の JSON シリアライザ)を使うのですから、属性
を付与してシリアライザによるデータのシリアル化 / 逆シリアル化を明示的に有効にするのは
必ずやっておくべきことのはずですし、推奨に反してまでつけない理由は何もないはずですし。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -