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

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

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

json文字列を整形しエスケープ済みのjson文字列の取得

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

■102762 / inTopicNo.1)  json文字列を整形しエスケープ済みのjson文字列の取得
  
□投稿者/ ded (12回)-(2023/12/23(Sat) 14:10:45)

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

VB.NET Framework 4.7.2 Winform Win10


REST APIから取得したjson文字列を、整形し、エスケープ済みの文字列にしたいです。


        ' 文字列これを...
        '{"value":[{"Data1":"AIUEO","Data2":"\u3042\u3044\u3046\u3048\u304A","Data3":"12345"},{"Data1":"Value","Data2":"!\u0022#$%\u0026\u0027()-=^~\\\\|@{\u002B*}\u003C\u003E?_","Data3":"ABCDEF"}]}

        ' 文字列こんな感じにしたい
        '{
        '  "value": [
        '    {
        '      "Data1": "AIUEO",
        '      "Data2": "あいうえお"
        '      "Data3": "12345"
        '    },
        '    {
        '      "Data1": "Value",
        '      "Data2": "!\"#$%&'()-=^~\\\\|@{+*}<>?_"
        '      "Data3": "ABCDEF"
        '    }
        '  ]
        '}

よろしくお願いいたします。

-----
Imports System.Text.Json

    Public Class clsItem
        Public Property Data1 As String
        Public Property Data2 As String
    End Class
    Public Class clsList
        Public Property value As New List(Of clsItem)
    End Class
    Sub Main()

        Dim list = New clsList()
        list.value.Add(New clsItem() With {.Data1 = "AIUEO", .Data2 = "あいうえお"})
        list.value.Add(New clsItem() With {.Data1 = "Value", .Data2 = "!""#$%&'()-=^~\\|@{+*}<>?_"})

        Dim jsonSiriOpt = New JsonSerializerOptions()
        Dim jsonSiriStr As String = JsonSerializer.Serialize(list, jsonSiriOpt)
        Console.WriteLine(jsonSiriStr)
        '{"value":[{"Data1":"AIUEO","Data2":"\u3042\u3044\u3046\u3048\u304A"},{"Data1":"Value","Data2":"!\u0022#$%\u0026\u0027()-=^~\\\\|@{\u002B*}\u003C\u003E?_"}]}
        '  ↓Data3プロパティありの時...
        '{"value":[{"Data1":"AIUEO","Data2":"\u3042\u3044\u3046\u3048\u304A","Data3":"12345"},{"Data1":"Value","Data2":"!\u0022#$%\u0026\u0027()-=^~\\\\|@{\u002B*}\u003C\u003E?_","Data3":"ABCDEF"}]}

        Dim jsonDeseOpt = New JsonSerializerOptions()
        Dim jsonDeseObj = JsonSerializer.Deserialize(Of clsList)(jsonSiriStr, jsonDeseOpt)
        For Each Item In jsonDeseObj.value
            Console.WriteLine($"Data1={Item.Data1}  Data2={Item.Data2}")
        Next
        'Data1=AIUEO  Data2=あいうえお
        'Data1=Value  Data2=!"#$%&'()-=^~\\|@{+*}<>?_

        ' こんな感じにしたい
        '{
        '  "value": [
        '    {
        '      "Data1": "AIUEO",
        '      "Data2": "あいうえお"
        '      "Data3": "12345"
        '    },
        '    {
        '      "Data1": "Value",
        '      "Data2": "!\"#$%&'()-=^~\\\\|@{+*}<>?_"
        '      "Data3": "ABCDEF"
        '    }
        '  ]
        '}

        '*************
        ' オブジェクト化しても良いが、取りこぼしがなければ(Data3があれば)OK
        Dim jsonOpt = New JsonSerializerOptions()
        jsonOpt.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
        jsonOpt.WriteIndented = True
        Dim jsonStr As String = JsonSerializer.Serialize(list, jsonOpt)
        Console.WriteLine(jsonStr)
        '{
        '  "value": [
        '    {
        '      "Data1": "AIUEO",
        '      "Data2": "あいうえお"
        '    },
        '    {
        '      "Data1": "Value",
        '      "Data2": "!\"#$%&'()-=^~\\\\|@{+*}<>?_"
        '    }
        '  ]
        '}
    End Sub

引用返信 編集キー/
■102764 / inTopicNo.2)  Re[1]: json文字列を整形しエスケープ済みのjson文字列の取得
□投稿者/ WebSurfer (2857回)-(2023/12/23(Sat) 14:33:07)
No102762 (ded さん) に返信

"\u3042\u3044\u3046\u3048\u304A" という形式は Unicode Escape Sequence といって
そのままでもあらゆる処理系で有効なはずですが、それを承知のうえで "あいうえお"
に直したいということですか?
引用返信 編集キー/
■102765 / inTopicNo.3)  Re[2]: json文字列を整形しエスケープ済みのjson文字列の取得
□投稿者/ ded (13回)-(2023/12/23(Sat) 15:05:02)
No102764 (WebSurfer さん) に返信
> ■No102762 (ded さん) に返信
> 
> "\u3042\u3044\u3046\u3048\u304A" という形式は Unicode Escape Sequence といって
> そのままでもあらゆる処理系で有効なはずですが、それを承知のうえで "あいうえお" 
> に直したいということですか?

はい。その通りです。
というか、自己解決しました。

ジェネリック型を指定せずに、Objectに代入後、
再度JsonSerializerOptionsで期待している形式に変換しました。

    Private Function DebugJsonText(jsonStr As String) As String
        Dim Result As String
        Dim obj As Object

        Dim jsonOpt = New JsonSerializerOptions()
        jsonOpt.WriteIndented = True
        jsonOpt.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
        obj = JsonSerializer.Deserialize(jsonStr, GetType(Object), jsonOpt)

        Result = JsonSerializer.Serialize(obj, jsonOpt)

        Return Result
    End Function

解決済み
引用返信 編集キー/
■102768 / inTopicNo.4)  Re[3]: json文字列を整形しエスケープ済みのjson文字列の取得
□投稿者/ WebSurfer (2858回)-(2023/12/23(Sat) 18:59:14)
No102765 (ded さん) に返信

> ジェネリック型を指定せずに、Objectに代入後、
> 再度JsonSerializerOptionsで期待している形式に変換しました。

JSON 文字列をデシリアライズした結果の .NET のクラス定義が不定なら JsonElement 構造体
にデシリアライズしてはいかがですか?

また、デシリアライズする際の JsonSerializerOptions の設定は不要です。

以下のようにして、

Imports System.IO
Imports System.Text.Encodings.Web
Imports System.Text.Json

Module Module1

    Sub Main()
        Dim path As String = "質問の json を格納したファイルへのパス"
        Dim jsonText As String = ""

        Using sr As StreamReader = File.OpenText(path)
            jsonText = sr.ReadToEnd()
        End Using

        Dim jElem = JsonSerializer.Deserialize(Of JsonElement)(jsonText)

        Dim jsonIndented = JsonSerializer.Serialize(jElem, New JsonSerializerOptions With {
                .WriteIndented = True,
                .Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
            })
        Console.WriteLine(jsonIndented)

    End Sub

End Module

結果は以下の通りとなります。

{
  "value": [
    {
      "Data1": "AIUEO",
      "Data2": "あいうえお",
      "Data3": "12345"
    },
    {
      "Data1": "Value",
      "Data2": "!\"#$%&'()-=^~\\\\|@{+*}<>?_",
      "Data3": "ABCDEF"
    }
  ]
}

JSON 文字列をデシリアライズした結果の .NET のクラス定義が決まっているなら、Visual Studio 
の機能を利用してクラス定義を生成し、それにデシリアライズすることもできます。

詳しくは以下の記事を見てください。

JSON 文字列から C# のクラス定義生成
http://surferonwww.info/BlogEngine/post/2020/05/10/generate-class-definition-from-json-string.aspx

引用返信 編集キー/
■102769 / inTopicNo.5)  Re[4]: json文字列を整形しエスケープ済みのjson文字列の取得
□投稿者/ WebSurfer (2859回)-(2023/12/23(Sat) 18:59:53)
解決済みマークをつけ忘れました
解決済み
引用返信 編集キー/
■102776 / inTopicNo.6)  Re[4]: json文字列を整形しエスケープ済みのjson文字列の取得
□投稿者/ WebSurfer (2862回)-(2023/12/24(Sun) 14:14:11)
No102768 で、

> JSON 文字列をデシリアライズした結果の .NET のクラス定義が決まっているなら、Visual Studio 
> の機能を利用してクラス定義を生成し、それにデシリアライズすることもできます。

と書きましたが、VB.NET の場合、紹介した記事の機能を使って生成したクラス定義では配列の定義
の方法の問題でデシリアライズできないので、そのことを書いておきます。

質問者さんの JSON 文字列から VB.NET のクラス定義を生成すると以下のようになります。

Public Class Rootobject
    Public Property value() As Value
End Class

Public Class Value
    Public Property Data1 As String
    Public Property Data2 As String
    Public Property Data3 As String
End Class

問題は Rootobject の value プロパティの定義で、以下のように変更しないと System.Test.Json 
でも Newtonsoft.json でもデシリアライズに失敗して例外がスローされます。

Public Property value As Value()

解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


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

このトピックに書きこむ