DOBON.NETプログラミング道掲示板

■35407 / 親記事)  JSONの複雑な入れ子内部の値を取りたい。
  
□投稿者/ けい 一般人(5回)-(2023/05/08(Mon) 15:13:41)
  • アイコン環境/言語:[VB.NET2022、Windows10] 
    分類:[.NET] 

    お世話になります。

    VB.NET2022のForm1にButton1とTextBox1を配置します。

    Button1を押すと、System.Text.jsonでJSONファイル(test.json)を読み込み、
    その中の項目の値をTextBox1に表示させます。

    JSONファイルがやや複雑で、値を取れる場合と取れない場合とがあり、
    取れない場合の改善方法を教えていただきたいと思っております。

    コードは以下の通りです。

    (コード)
    -----------------------------------------------------------
    Imports System.IO
    Imports System.Runtime
    Imports System.Text

    Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Dim enc As Encoding = Encoding.UTF8
    Dim jsonStr As String = ""
    Dim jsonFilePath As String = "C:\test.json"

    Using sr As New System.IO.StreamReader(jsonFilePath, enc)
    jsonStr = sr.ReadToEnd()
    End Using

    Dim jsonNode = System.Text.Json.Nodes.JsonNode.Parse(jsonStr)
    TextBox1.Text = <(下記参照)>'・・・・・・・・・・・・A

    End Sub

    End Class

    -----------------------------------------------------------
    また、JSONファイルの内容は、
    以下のようになっています。
    -----------------------------------------------------------
    {
    "ResultInfo": {'・・・・・・・・・・・・・・・・・・・・・・B
    "Count": 1,
    "Total": 1,
    "Start": 1,
    "Status": 200,
    "Description": "",
    "Copyright": "",
    "Latency": 0.017
    },'・・・・・・・・・・・・・・・・・・・・・・・・・・・・・C
    "Feature": ['・・・・・・・・・・・・・・・・・・・・・・・・・・・D
    {
    "Id": "8d8acd6f1e7d81d5d10a9a18e8e927ec",
    "Gid": "",
    "Name": "\u3012234-0054",
    "Geometry": {
    "Type": "point",
    "Coordinates": "139.58691098,35.37690957"
    },
    "Category": [
    "\u90F5\u4FBF\u756A\u53F7",
    "\u753A\u57DF\u90F5\u4FBF\u756A\u53F7"
    ],
    "Description": "Yahoo!\u90F5\u4FBF\u756A\u53F7\u691C\u7D22",
    "Style": [],
    "Property": {
    "Uid": "1831ff4e59f55c19370fc71002827b41f317f341",
    "CassetteId": "3ee7f7f5fe1ef2267e319b15168e37d3",
    "Country": {
    "Code": "JP",
    "Name": "\u65E5\u672C"
    },
    "Address": "\u795E\u5948\u5DDD\u770C\u6A2A\u6D5C\u5E02\u6E2F\u5357\u533A\u6E2F\u5357\u53F0",
    "GovernmentCode": "14111",
    "AddressMatchingLevel": "6",
    "PostalName": "\u795E\u5948\u5DDD\u770C\u6A2A\u6D5C\u5E02\u6E2F\u5357\u533A\u6E2F\u5357\u53F0",
    "Station": [
    {
    "Id": "23365",
    "SubId": "2336501",
    "Name": "\u6D0B\u5149\u53F0",
    "Railway": "JR\u5728\u6765\u7DDA",
    "Exit": "\u51FA\u53E3",
    "ExitId": "5999",
    "Distance": "1123",
    "Time": "14",
    "Geometry": {
    "Type": "point",
    "Coordinates": "139.596374,35.378634"
    }
    },
    {
    "Id": "23157",
    "SubId": "2315701",
    "Name": "\u6E2F\u5357\u53F0",
    "Railway": "JR\u5728\u6765\u7DDA",
    "Exit": "\u51FA\u53E3",
    "ExitId": "5628",
    "Distance": "1316",
    "Time": "16",
    "Geometry": {
    "Type": "point",
    "Coordinates": "139.576543,35.375218"
    }
    },
    {
    "Id": "23158",
    "SubId": "2315801",
    "Name": "\u6E2F\u5357\u4E2D\u592E",
    "Railway": "\u6A2A\u6D5C\u5E02\u55B6\u5730\u4E0B\u9244\u30D6\u30EB\u30FC\u30E9\u30A4\u30F3",
    "Exit": "2",
    "ExitId": "5630",
    "Distance": "3334",
    "Time": "41",
    "Geometry": {
    "Type": "point",
    "Coordinates": "139.591038,35.401302"
    }
    }
    ],
    "OpenForBusiness": "",
    "Detail": {
    "PcUrl1": "http://www.post.japanpost.jp/cgi-zip/zipcode.php?zip=234-0054"
    }
    }
    }
    ]'・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・E
    }

    -----------------------------------------------------------

    上記のAのところで、
    下記のように書いた場合、
    成功するものと失敗するものとがあります。

    (成功)

    TextBox1.Text = jsonNode("ResultInfo").ToString
    B〜Cが取得される。

    TextBox1.Text = jsonNode("ResultInfo").Item("Latency").ToString
    "Latency"の値が表示される。

    TextBox1.Text = jsonNode("Feature").ToString
    D〜Eが取得される。

    (失敗)

    TextBox1.Text = jsonNode("Feature").Item("Id").ToString
    「System.InvalidOperationException: 'The node must be of type 'JsonObject'.'」

    TextBox1.Text = jsonNode("Property").ToString
    TextBox1.Text = jsonNode("Station").ToString
    「System.NullReferenceException: 'Object reference not set to an instance of an object.'System.Text.Json.Nodes.JsonNode.this[string].get が Nothing を返しました。」

    という具合です。

    JSONファイルの内容自体は、Visual Studio Code上で、
    特に構文的間違いは出てきません。

    jsonNode("Feature")の内部の各項目の値を取得するには、どのように書けばよいか、ご教示ください。

    よろしくお願い申し上げます。



マルチポストを報告
違反を報告
引用返信 削除キー/
■35408 / ResNo.1)  Re[1]: JSONの複雑な入れ子内部の値を取りたい。
□投稿者/ Hongliang 大御所(639回)-(2023/05/08(Mon) 21:24:21)
  • アイコン> TextBox1.Text = jsonNode("Feature").Item("Id").ToString
    > 「System.InvalidOperationException: 'The node must be of type 'JsonObject'.'」

    > "Feature": ['・・・・・・・・・・・・・・・・・・・・・・・・・・・D
    > {
    > "Id": "8d8acd6f1e7d81d5d10a9a18e8e927ec",

    Featureは配列型ですね。
    jsonNode("Feature")(0)("Id")
    のように、Featureの、先頭要素の、Idプロパティ、とアクセスする必要があります。

    > TextBox1.Text = jsonNode("Property").ToString
    > TextBox1.Text = jsonNode("Station").ToString
    > 「System.NullReferenceException: 'Object reference not set to an instance of an object.'System.Text.Json.Nodes.JsonNode.this[string].get が Nothing を返しました。」

    jsonNodeがルート指したままであれば(Parseしたのを代入したままで再代入していないのであれば)、jsonNodeはこのJSONのルートオブジェクトを指しています。
    JSONのルートオブジェクトは、ResultInfoとFeatureの2つのプロパティしか持っていないので、("Property") や ("Station") は何も返すことができません。
    Dim feature As JsonNode = jsonNode("Feature")(0)
    としたうえで
    .Text = feature("Property").ToString()
    .Text = feature("Property")("Station").ToString()
    とか、更に
    Dim prop As JsonNode = feature("Property")
    .Text = prop.ToString()
    .Text = prop("Station").ToString()
    とするとかする必要があります。

    お使いのVisual Studioによっては、「形式を指定して貼り付け」を使えるかもしれません。
    https://qiita.com/Midoliy/items/362bbb95a5c78c6aa401
    // VBでも使えるかどうかは不明。
    あるいはJSONからC#クラスへの変換はネットにサービスとしても存在しているので、
    https://json2csharp.com/
    さらにC#-VB変換サービスを適用することでもクラス生成はできそうです。

    これらでクラスを生成できれば、JsonNodeを使わずとも、
    System.Text.Json.JsonSerialzier.Deserialize(Of 生成したクラス)
    メソッドを使ってオブジェクトとして扱うことができます。
違反を報告
引用返信 削除キー/
■35409 / ResNo.2)  Re[2]: JSONの複雑な入れ子内部の値を取りたい。
□投稿者/ けい 一般人(6回)-(2023/05/09(Tue) 10:38:27)
  • アイコンNo35408に返信(Hongliangさんの記事)

    お詳しくありがとうございます^^。

    実行してみます。

    結果が出ましたら再度ご返事させていただきます。
違反を報告
引用返信 削除キー/
■35410 / ResNo.3)  Re[3]: JSONの複雑な入れ子内部の値を取りたい。
□投稿者/ けい 一般人(7回)-(2023/05/09(Tue) 15:28:24)
  • アイコンNo35408に返信(Hongliangさんの記事)

    いただきましたご指摘を参考に、
    JSONファイルにおける各値を取得できました。

    今回は、JSON.NETよりも推奨されているSystem.Text.jsonのJsonNodeを使う方向になりました。

    クラスについては今後検討していきたいと思います。

    まことにありがとうございました。

    以下、各項目の値を取得した際の表記を記載させていただきます。


    "ResultInfo"

    "Count": 1 ///jsonNode("ResultInfo")("Count")
    "Total": 1 ///jsonNode("ResultInfo")("Total")
    "Start": 1 ///jsonNode("ResultInfo")("Start")
    "Status": 200 ///jsonNode("ResultInfo")("Status")
    "Description": "" ///jsonNode("ResultInfo")("Description")
    "Copyright": "" ///jsonNode("ResultInfo")("Copyright")
    "Latency": 0.049 ///jsonNode("ResultInfo")("Latency")

    "Feature"

    "Id": "8d8acd6f1e7d81d5d10a9a18e8e927ec" /// jsonNode("Feature")(0)("Id")
    "Gid": "" /// jsonNode("Feature")(0)("Gid")
    "Name": "〒234-0054" /// jsonNode("Feature")(0)("Name")

    "Type": "point" /// jsonNode("Feature")(0)("Geometry")("Type")
    "Coordinates": "139.58691098,35.37690957" /// jsonNode("Feature")(0)("Geometry")("Coordinates")


    "Description": "Yahoo!郵便番号検索" ///jsonNode("Feature")(0)("Description")
    "Style": [] ///jsonNode("Feature")(0)("Style")

    "Uid": "1831ff4e59f55c19370fc71002827b41f317f341" /// jsonNode("Feature")(0)("Property")("Uid")
    "CassetteId": "3ee7f7f5fe1ef2267e319b15168e37d3" /// jsonNode("Feature")(0)("Property")("CassetteId")

    "Code": "JP" /// jsonNode("Feature")(0)("Property")("Country")("Code")
    "Name": "日本" /// jsonNode("Feature")(0)("Property")("Country")("Name")

    "Address": "神奈川県横浜市港南区港南台" /// jsonNode("Feature")(0)("Property")("Address")
    "GovernmentCode": "14111" /// jsonNode("Feature")(0)("Property")("GovernmentCode")
    "AddressMatchingLevel": "6" /// jsonNode("Feature")(0)("Property")("AddressMatchingLevel")
    "PostalName": "神奈川県横浜市港南区港南台" /// jsonNode("Feature")(0)("Property")("PostalName")

    "Id": "23365" /// jsonNode("Feature")(0)("Property")("Station")(0)("Id")
    "SubId": "2336501" /// jsonNode("Feature")(0)("Property")("Station")(0)("SubId")
    "Name": "洋光台" ///jsonNode("Feature")(0)("Property")("Station")(0)("Name")
    "Railway": "JR在来線" ///jsonNode("Feature")(0)("Property")("Station")(0)("Railway")
    "Exit": "出口" ///jsonNode("Feature")(0)("Property")("Station")(0)("Exit")
    "ExitId": "5999" ///jsonNode("Feature")(0)("Property")("Station")(0)("ExitId")
    "Distance": "1123" ///jsonNode("Feature")(0)("Property")("Station")(0)("Distance")
    "Time": "14" ///jsonNode("Feature")(0)("Property")("Station")(0)("Time")
    "Type": "point" ///jsonNode("Feature")(0)("Property")("Station")(0)("Geometry")("Type")
    "Coordinates": "139.596374,35.378634" ///jsonNode("Feature")(0)("Property")("Station")(0)("Geometry")("Coordinates")

    "Id": "23157" /// jsonNode("Feature")(0)("Property")("Station")(1)("Id")
    "SubId": "2315701" /// jsonNode("Feature")(0)("Property")("Station")(1)("SubId")
    "Name": "港南台" ///jsonNode("Feature")(0)("Property")("Station")(1)("Name")
    "Railway": "JR在来線" ///jsonNode("Feature")(0)("Property")("Station")(1)("Railway")
    "Exit": "出口" ///jsonNode("Feature")(0)("Property")("Station")(1)("Exit")
    "ExitId": "5628" ///jsonNode("Feature")(0)("Property")("Station")(1)("ExitId")
    "Distance": "1316" ///jsonNode("Feature")(0)("Property")("Station")(1)("Distance")
    "Time": "16" ///jsonNode("Feature")(0)("Property")("Station")(1)("Time")
    "Type": "point" ///jsonNode("Feature")(0)("Property")("Station")(1)("Geometry")("Type")
    "Coordinates": "139.576543,35.375218" ///jsonNode("Feature")(0)("Property")("Station")(1)("Geometry")("Coordinates")

    "Id": "23158" /// jsonNode("Feature")(0)("Property")("Station")(2)("Id")
    "SubId": "2315801" /// jsonNode("Feature")(0)("Property")("Station")(2)("SubId")
    "Name": "港南中央" ///jsonNode("Feature")(0)("Property")("Station")(2)("Name")
    "Railway": "横浜市営地下鉄ブルーライン" ///jsonNode("Feature")(0)("Property")("Station")(2)("Railway")
    "Exit": "2" ///jsonNode("Feature")(0)("Property")("Station")(2)("Exit")
    "ExitId": "5630" ///jsonNode("Feature")(0)("Property")("Station")(2)("ExitId")
    "Distance": "3334" ///jsonNode("Feature")(0)("Property")("Station")(2)("Distance")
    "Time": "41" ///jsonNode("Feature")(0)("Property")("Station")(2)("Time")
    "Type": "point" ///jsonNode("Feature")(0)("Property")("Station")(2)("Geometry")("Type")
    "Coordinates": "139.591038,35.401302" ///jsonNode("Feature")(0)("Property")("Station")(2)("Geometry")("Coordinates")

    "OpenForBusiness": "" /// jsonNode("Feature")(0)("Property")("OpenForBusiness")
    "PcUrl1": http://www.post.japanpost.jp/cgi-zip/zipcode.php?zip=234-0054 /// jsonNode("Feature")(0)("Property")("Detail")("PcUrl1")


解決み!
違反を報告
引用返信 削除キー/



スレッド内ページ移動 / << 0 >>

このスレッドに書きこむ

Mode/  Pass/


- Child Tree -