質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

MFC

MFC (Microsoft Fouondation Class)とは、MicrosoftがVC++用に開発したWindows用アプリケーションのフレームワークです。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Q&A

0回答

719閲覧

Win10 VS2015 VC++ MFC (Unicode)で漢字入りJSONを正しく読み書きできるライブラリは実在するか。

Kazumori102

総合スコア45

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

MFC

MFC (Microsoft Fouondation Class)とは、MicrosoftがVC++用に開発したWindows用アプリケーションのフレームワークです。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

0グッド

0クリップ

投稿2022/08/11 06:29

編集2022/08/20 12:41

前提

まず、経験の浅い物のため、ものをあまり知らないことを許していただきたい。

表題の環境下でJSONライブラリで漢字入りJSONを読み込もうとし、下記のライブラリを試したが、エスケープキャラクターでエラーが出る。
JSONはUTF-8でエンコードされているからダメ文字等はないはずだが、この問題が起きる。

  • PicoJSON
  • RapidJSON
  • nlohmnn-jsonn
  • Json11

規格上漢字をはじめとする日本語は要エンコードではないということも確認した。
デバッグしていくと、ファイルの読み込みはともかく、ライブラリにデータを渡した後にエラーが起きているように見える。
ただし、Win環境はエンコード周りが怪しい…。
なお、RapidJSONはダメ文字をバックスラッシュで回避することで読み込めたが、本来不要な処理なはずである。
Linux上では正常に動いている様子はよく見かけるが…。

実現したいこと

漢字入りJSONを正しく読み込めるライブラリ、もしくは上記の試したライブラリの正しい扱い方を知る。

下記はBOM無しUTF-8でエンコードし保存 (補足要求を念のためこちらでも回答)

kanji_included.json

1{ 2 "bad_string" : "表現" 3}

発生している問題・エラーメッセージ

エスケープシーケンスが含まれる等のメッセージ

該当のソースコード

現在使用しているコード

C++

1FILE* fileR; //読込用ファイルポインタ 2CString bufReadJSON; //読込バッファ 3CString csResultReadJSON = NULL; //読込結果 4 5CStdioFile cFileR(fileR); //読込用ファイルポインタの変形したもの 6 7while (cFileR.ReadString(bufReadJSON)) { 8 csResultReadJSON += bufReadJSON + _T("\n"); 9} 10 11CStringA csaResultReadJSON(csResultReadJSON.GetBuffer(0)); 12std::string ssResultReadJSON = csaResultReadJSON.GetBuffer(0); 13csResultReadJSON.ReleaseBuffer(0); 14csaResultReadJSON.ReleaseBuffer(0); 15 16rapidjson::Document hoge 17 18hoge.Parse(ssResultReadJSON.c_str()); 19ssResultReadJSON.clear();

→パースされずにエスケープシーケンスエラー

std::stringの内部表現をShiftJISからUTF-8に変えるらしいコードを試した

C++

1std::string ssu8ResultReadJSON = ""; 2 3std::ifstream ifs; 4ifs.open(PARAMSAVE, std::ios::binary); 5 6std::string ssBufReadJSON; 7while (getline(ifs, ssBufReadJSON)) { 8 ssu8ResultReadJSON += ssBufReadJSON; 9} 10 11int lenUni = MultiByteToWideChar(CP_UTF8, 0, ssu8ResultReadJSON.c_str(), ssu8ResultReadJSON.size() + 1, NULL, 0); 12 13wchar_t* bufUni = new wchar_t[lenUni]; 14 15MultiByteToWideChar(CP_UTF8, 0, ssu8ResultReadJSON.c_str(), ssu8ResultReadJSON.size() + 1, bufUni, lenUni); 16 17int lenSJ = WideCharToMultiByte(CP_THREAD_ACP, 0, bufUni, -1, NULL, 0, NULL, NULL); 18 19char* cpResultReadJSON = new char[lenSJ]; 20 21WideCharToMultiByte(CP_THREAD_ACP, 0, bufUni, lenUni + 1, cpResultReadJSON, lenSJ, NULL, NULL); 22 23rapidjson::Document hoge 24hoge.Parse(cpResultReadJSON);

→ダメだった。(詳細失念)
文字化けかエスケープシーケンスエラーのどちらかの発生。

Json11を使ってみた

C++

1FILE* fileR = NULL; //読込用ファイルポインタ 2CStdioFile cFileR; 3CString bufReadJSON; //読込バッファ 4CString csResultReadJSON = NULL; //読込結果 5 6_tfopen_s(&fileR, PARAMSAVE, _T("r,ccs=UTF-8")); 7 8 9CStdioFile cFileR(fileR); //読込用ファイルポインタの変形したもの 10 11while (cFileR.ReadString(bufReadJSON)) { 12 csResultReadJSON += bufReadJSON + _T("\n"); 13} 14 15CStringA csaResultReadJSON(csResultReadJSON.GetBuffer(0)); 16std::string ssResultReadJSON = csaResultReadJSON.GetBuffer(0); 17csResultReadJSON.ReleaseBuffer(0); 18csaResultReadJSON.ReleaseBuffer(0); 19std::string ssErr; 20jsonDoc.ParseString(ssResultReadJSON, ssErr);

→パースされずにエスケープシーケンスエラー

Json11使ってみた(2:std::stringに統一)

C++

1std::string ssResultReadJSON = ""; 2 3std::ifstream ifs; 4ifs.open(PARAMSAVE, std::ios::binary); 5 6std::string ssBufReadJSON; 7while (getline(ifs, ssBufReadJSON)) { 8 ssResultReadJSON += ssBufReadJSON; 9} 10 11std::string ssErr; 12auto jsonDoc = json11::Json::parse(ssResultReadJSON, ssErr);

→パースはされるが出力すると文字化けている。

試したこと

ファイルの読み出し方を変えたり、CStringに入れたりStd::Stringに入れたり、変換方法を変えてみたりした。
上記の通り持ち帰られないので例示が効かない。
上記に書き足し。上記の通りダメなものばかり。

補足情報(FW/ツールのバージョンなど)

さらに詳細な情報の希望があれば可能な限り開示。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2022/08/11 06:36

> kanji_included.json このファイルのエンコードは何にしていますか?
Kazumori102

2022/08/11 06:44

勿論BOM無しUTF-8です。
maisumakun

2022/08/11 06:54 編集

MFCがUnicode版ということは、CStringもwcharをベースとしたものになっていますが、ライブラリはcharベース、なんてことはありませんか?
Kazumori102

2022/08/11 06:58

ご返信ありがとうございます。 うすうすそういうこと原因で起きてそうというのは気づいているんですが、では、どれならいいのかというのが見当がつかずです…。 RapidJSONは標準のDocument型以外を使えばいろんな型、エンコードに対応できるっぽいというのは記事で見かけましたが、そこに詳しく言及しているところは(今の検索状況では)見当たらず…。 論点整理のご協力ありがとうございます。
dodox86

2022/08/12 07:09

> 表題の環境下でJSONライブラリで漢字入りJSONを読み込もうとし、下記のライブラリを試したが、エスケープキャラクターでエラーが出る。 エラーが報告されるのはライブラリのAPI/関数などの実行時ですか。それともそれを利用しているMFC含むアプリ側でしょうか。 RapidJSONのドキュメントを読むと、UTF-8の文字列を取り扱う限りはライブラリ内ではうまく動きそうにも思いますが。 https://rapidjson.org/md_doc_encoding.html これを、UNICODEビルドのMFCアプリでCString(CStringW)やstd::string、std::wstringなどの利用を不用意に混在させるとダメだと思います。 UTF-8のJSONファイルや文字列のバイナリイメージを扱う部分では全てRapidJSONのライブラリだけを使って、アプリで必要なデータは注意深く、適時、UTF-8からWindowsのUTF-16(LE)にMultiByteToWideChar APIを利用するなどして変換して扱えば良いのではないでしょうか。 https://docs.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-multibytetowidechar こちらで即、試せる環境にないのであくまで推測ですが。
Kazumori102

2022/08/12 07:34

一度 ifstreamなどを用いてstdライブラリのみで文字を取り扱おうとしましたが、RapidJSONはどのみちchar*型への変換が必要だったり、変換不要で直で読めるライブラリ(残念ながら名前失念)においてもダメでした。 std::stringはWin環境ではShiftJISで実装されているせいだとか?でダメでした。 wstringで運用する方針も考えましたが、資料が乏しくしんどいです。 MFCのみでのデータのやり取りを完結させようとしましたが、ダメで…。 試したデータが手元と脳内になくて疑似コードでも実例が示せないので、空中戦気味になってしまい申し訳ない。 ドキュメントを見る限りRapidJSONはUTF16のデータを読みに行かせることも出きるっぽいのですが、如何せん実例が少なく。
dodox86

2022/08/12 08:01

> std::stringはWin環境ではShiftJISで実装されているせいだとか?でダメでした。 シフトJISもそうですが、charの配列、char*型の型はUTF-8も非UTF-8のANSI/シフトJIS含むマルチバイト文字列のどちらもとりあえずNULL文字終端なら格納だけは可能なので、不用意に混在させるとメンバー関数の利用時に誤動作を起こすのでダメなのでは、と言う指摘です。これ以上は実例のコード無しだとちょっと埒があきませんね。
Kazumori102

2022/08/20 12:41

追加しました。よろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問