none
Encoding.UTF8での改行コードの扱い RRS feed

  • 質問

  • Encoding.UTF8で次の様な文字列をGetBytesでUTF8に変換しました

    "文字列" + Environment.NewLine + "文字列"

    出力されたバイト列の中に改行に該当する0x0d, 0x0aのコードが有る事を期待していたのですが,そこに有ったのは次の様なコードでした.

    0x5c, 0x75, 0x30, 0x30, 0x30, 0x64, 0x5c, 0x75, 0x30, 0x30, 0x30, 0x61

    \u000d\u000aを表していますがUTF8を受け取る側は.NETでは無いので正常に改行出来ません.

    普通に0x0d, 0x0aにするにはどうすればいいでしょうか?

    バイト列から上記コードを探して書き換えてもいいのですが,無駄な手間に成りますし.

    2014年6月23日 7:35

回答

  • なんとなくそれっぽいと思ってましたが、やはりJsonですか。

    まず、改行文字を\u000d\u000aに変換しているのはDynamicJsonの内部実装であってEncodingオブジェクトとは関係ありません。

    また、http://wiki.suikawiki.org/n/JSONの「文字列」の項目にありますが、\uXXXXはJsonとして正当なエスケープです。受け取るJsonデコーダは正しくU+XXXXの文字として扱えなければなりません。

    同ページにあるように\r, \nも正当ではありますが、少なくともJsonReaderWriterFactoryが作るXmlDictionaryWriterにおいて、\r\nを\u000d\u000aに変換するのは変更しがたい動作なので、どうしてもこれが受け入れがたいのであれば、Json文字列を生成後にReplaceなどで置換することになるでしょう。

    2014年6月23日 15:52
  • 補足で、 json.org の右側に仕様が記されています。 string / chars / char を追っていけばはっきりします。文字列としては " と \ 以外は任意の文字を扱うことができ、質問にある改行コード CR LF もそのまま埋め込むことは可能です。

    しかしJSON文字列はあくまで通常のテキストでしかないため、通信中に改行記号が変更されたりタブがスペースに展開されたり等の危険性を考えると、CR LF をそのまま埋め込むのでなく、 \r \n や今回のように \u000D \u000A とエスケープするのが一般的です。
    加えて質問者さんは UTF-8 と書かれていますが、JSON文字列にはエンコーディングが何であるかを伝える手段がないため、漢字など非ASCII文字についても \uXXXX エスケープを行い、JSON文字列自身はUS-ASCIIに収めることも一般的です。

    .NET Frameworkの動作を疑う前に、ご自身の扱おうとしているデータ型について正しい理解をすべきかと思います。

    2014年6月23日 22:43

すべての返信

  • 普通にやるとそうはなりません。ですので、具体的なコードを示してください。それからバイト列の確認方法も。

    // Environment.NewLineはクラス名通り実行環境依存の文字列なので、実行環境も併記してください。

    2014年6月23日 7:49
  • 普通にやるとそうはならないのですか.

    確かに変わったやり方をしています.

    dynamic send = new DynamicJson();
    try
    {
    List<dynamic> couponList = new List<dynamic>();
    if (cache.ContainsKey(received.data.identifier))
    {
    foreach (Coupon record in cache[received.data.identifier])
    {
    dynamic coupon = new
    {
    identifier = record.identifier,
    title = record.title,
    detail = record.detail,
    usedCount = record.usedCount,
    };
    couponList.Add(coupon);
    }
    }
    send.result = "OK";
    send.list = couponList.ToArray();
    }
    return Encoding.UTF8.GetBytes(send.ToString());

    こんな感じでJsonの文字列の中に改行が入っているんです.

    実行しているのはWindows 7でVS Express 2013 for Windows Desktopです.

    最後のToStringを調べてみた方が良さそうですね.

    2014年6月23日 14:26
  • なんとなくそれっぽいと思ってましたが、やはりJsonですか。

    まず、改行文字を\u000d\u000aに変換しているのはDynamicJsonの内部実装であってEncodingオブジェクトとは関係ありません。

    また、http://wiki.suikawiki.org/n/JSONの「文字列」の項目にありますが、\uXXXXはJsonとして正当なエスケープです。受け取るJsonデコーダは正しくU+XXXXの文字として扱えなければなりません。

    同ページにあるように\r, \nも正当ではありますが、少なくともJsonReaderWriterFactoryが作るXmlDictionaryWriterにおいて、\r\nを\u000d\u000aに変換するのは変更しがたい動作なので、どうしてもこれが受け入れがたいのであれば、Json文字列を生成後にReplaceなどで置換することになるでしょう。

    2014年6月23日 15:52
  • 補足で、 json.org の右側に仕様が記されています。 string / chars / char を追っていけばはっきりします。文字列としては " と \ 以外は任意の文字を扱うことができ、質問にある改行コード CR LF もそのまま埋め込むことは可能です。

    しかしJSON文字列はあくまで通常のテキストでしかないため、通信中に改行記号が変更されたりタブがスペースに展開されたり等の危険性を考えると、CR LF をそのまま埋め込むのでなく、 \r \n や今回のように \u000D \u000A とエスケープするのが一般的です。
    加えて質問者さんは UTF-8 と書かれていますが、JSON文字列にはエンコーディングが何であるかを伝える手段がないため、漢字など非ASCII文字についても \uXXXX エスケープを行い、JSON文字列自身はUS-ASCIIに収めることも一般的です。

    .NET Frameworkの動作を疑う前に、ご自身の扱おうとしているデータ型について正しい理解をすべきかと思います。

    2014年6月23日 22:43
  • そうですね.

    Jsonに対して理解が足りませんでした.

    問題は受ける側のJsonパースの方でした.

    それはそれで困るんですがw

    2014年6月24日 2:19
  • お二方ありがとうございました.

    結局パースした先のプログラムに不具合が有りましたw

    流れてるJsonを見て変だと勘違いしたのが回り道の原因でした

    助かりました.

    2014年6月24日 7:05