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

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

新規登録して質問してみよう
ただいま回答率
85.47%
VC++

VC++ (Visual C++) とは、Microsoft製のC++のための統合開発環境です。

cURL

cURLはHTTP, FTPやTelnetなど複数のプロトコルを用いてデータを転送するライブラリとコマンドラインツールを提供します。

Q&A

解決済

1回答

1800閲覧

HTTPレスポンス内に含まれる日本語がUnicode文字になる。

keroyu

総合スコア1

VC++

VC++ (Visual C++) とは、Microsoft製のC++のための統合開発環境です。

cURL

cURLはHTTP, FTPやTelnetなど複数のプロトコルを用いてデータを転送するライブラリとコマンドラインツールを提供します。

0グッド

0クリップ

投稿2022/05/05 15:44

前提と問題

curlを用いてMediaWikiのAPIを叩き、特定のページのwikitextを得るプログラムを、C++を用いて組んでいます。実行時、レスポンス自体は正しく返ってくる(ステータスコードが200)のですが、レスポンスに含まれる日本語がUnicode文字として返ってきてしまいます。

実現したいこと

  • レスポンスを、後述の期待する出力の項に示されるような形式で得たい。

該当のソースコード

以下Main()関数内。変数urlはUITF8でパーセントエンコーディングされたURL。

c++

1 CURL* curl = curl_easy_init(); 2 Buffer* buf = new Buffer(); 3 4 //ヘッダー 5 curl_slist* headers = nullptr; 6 headers = curl_slist_append(headers, "Content-Type : application/json; charset=utf-8"); 7 8 curl_easy_setopt(curl, CURLOPT_URL, url); 9 curl_easy_setopt(curl, CURLOPT_WRITEDATA, buf); 10 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback); 11 curl_easy_setopt(curl, CURLOPT_HEADER, headers); 12 curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "UTF-8"); 13 14 15 curl_easy_perform(curl); 16 long* response_code = (long*)malloc(sizeof(long)); 17 18 //ステータスコード 19 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, response_code); 20 21 char end = '\0'; 22 buf->data = (char*)realloc(buf->data, buf->data_size + sizeof(char)); 23 24 memcpy(buf->data + buf->data_size, &end, sizeof(char)); 25 26 curl_easy_cleanup(curl); 27 28 delete(buf);

以下Main()内で使用した自作関数と自作クラス

c++

1struct Buffer { 2 char* data = nullptr; 3 int data_size = 0; 4}; 5 6 7//curlのコールバック 8size_t callback(void* buffer, size_t size, size_t nmemb, void* userp) { 9 size_t realsize = size * nmemb; 10 Buffer* buf = (Buffer*)userp; 11 if (buf == nullptr) return realsize; 12 13 if (!buf->data) { 14 buf->data = (char*)malloc(realsize); 15 } 16 else { 17 buf->data = (char*)realloc(buf->data, buf->data_size + realsize); 18 } 19 20 if (buf->data) { 21 memcpy(buf->data + buf->data_size, buffer, realsize); 22 buf->data_size += realsize; 23 } 24 25 return realsize; 26} 27

コード実行時の、curl_easy_cleanup(curl);でブレークした際のbuf->dataの内容

HTTP/1.1 200 OK Connection: keep-alive Content-Length: 2185 content-type: application/json; charset=utf-8 x-content-type-options: nosniff x-frame-options: DENY content-disposition: inline; filename=api-result.json cache-control: private, must-revalidate, max-age=0 x-envoy-upstream-service-time: 70 X-Datacenter: SJC Accept-Ranges: bytes X-Cacheable: NO:Cache-Control=private Date: Thu, 05 May 2022 15:09:07 GMT X-Served-By: cache-wk-sjc11421-SJC, cache-tyo11922-TYO X-Cache: MISS, MISS X-Cache-Hits: 0, 0 X-Timer: S1651763347.149674,VS0,VE177 Vary: Accept-Encoding, Treat-as-Untrusted, Cookie Set-Cookie: wikia_beacon_id=YH1Gq-ALwC; domain=.fandom.com; path=/; expires=Tue, 01 Nov 2022 15:09:07 GMT; SameSite=None; Secure; Set-Cookie: wikia_session_id=zjwddvu88d; domain=.fandom.com; path=/; expires=Thu, 05 May 2022 15:39:07 GMT; SameSite=None; Secure; Set-Cookie: _b2=ZYE7xfiRcH.1651763347150; domain=.fandom.com; path=/; expires=Sat, 04 May 2024 15:09:07 GMT; SameSite=None; Secure; Set-Cookie: Geo={%22region%22:%2208%22%2C%22city%22:%22tsukuba%22%2C%22country_name%22:%22japan%22%2C%22country%22:%22JP%22%2C%22continent%22:%22AS%22}; path=/; domain=.fandom.com; SameSite=None; Secure; {"parse":{"title":"SCP-165-JP \u30d8\u30a4\u30eb\u30b0\u30ed\u30fc\u30d6","pageid":6907,"wikitext":{"*":"{{Cardtable| card_type = \u30aa\u30d6\u30b8\u30a7\u30af\u30c8| sub_type = | type = Euclid| number = 165| name = SCP-165-JP \u30d8\u30a4\u30eb\u30b0\u30ed\u30fc\u30d6| image =420dfff8-eccc-4ee0-8092-50f2734d8d53.jpg| object_class =Euclid| attack =0| cost =2| effect_text =\u2460\u3053\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306f\u8ca1\u56e3\u4e0a\u3092\u96e2\u308c\u306a\u3044\u3002<br> \u2461\u81ea\u5206\u306e\u30bf\u30fc\u30f3\u958b\u59cb\u6642\u306b\u767a\u52d5\u3059\u308b\u3002\u81ea\u5206\u307e\u305f\u306f\u76f8\u624b\u4eba\u4e8b\u3092\u3053\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u4e0b\u306b\u91cd\u306d\u308b\u3002<br> \u2462\u2461\u306e\u52b9\u679c\u3092\u767a\u52d5\u3057\u3066\u304b\u30895\u30bf\u30fc\u30f3\u5f8c\u306e\u30bf\u30fc\u30f3\u7d42\u4e86\u6642\u306b\u767a\u52d5\u3059\u308b\u3002\u3053\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u4e0b\u306b\u5b58\u5728\u3059\u308b\u4eba\u4e8b\u3092decommissioned\u306b\u9001\u308b\u3002<br>| flavor_text = \u5c0f\u585a\u7814\u7a76\u54e1: \u8336\u8272\u3058\u3083\u3054\u4e0d\u6e80\u304b\u3002<br><br>SCP-165-JP-A: \u52ff\u8ad6\uff01 \u3082\u3046\u5c11\u3057\u660e\u308b\u3044\u8272\u306e\u65b9\u304c\u3044\u3044\u306d\u3002<br> \u305d\u308c\u3068\u3053\u306e\u5b89\u3063\u307d\u3055\u304c\u6c17\u306b\u5165\u3089\u306a\u3044\u30022000\u5186\u3082\u3057\u306a\u3044\u306a\u3053\u308c\u306f\u3002<br>| tags =scp-jp \u4eba\u9593\u578b \u5bb9\u5668 \u77ac\u9593\u79fb\u52d5 \u7cbe\u795e\u5f71\u97ff| limited = | effect_tags = |source =<span class=\"ui_wikidb_title\">\u51fa\u5178</span>&nbsp;JP<br><span class=\"ui_bottom_detail\">\"kasyu-maki\"\u4f5c SCP-165-JP - \u30d8\u30a4\u30eb\u30b0\u30ed\u30fc\u30d6<br>\"https://scptcgjpjwiki.gamerch.com/gamerch/external_link/?url=http%3A%2F%2Fja.scp-wiki.net%2Fscp-165-jp\" http://ja.scp-wiki.net/scp-165-jp<br><br>\u30ab\u30fc\u30c9\u516c\u958b\u5148<br>\"https://scptcgjpjwiki.gamerch.com/gamerch/external_link/?url=https%3A%2F%2Ftwitter.com%2Fkeroyu_scp%2Fstatus%2F1283263861898932224\" https://twitter.com/keroyu_scp/status/1283263861898932224<br></span>}}"}}}

期待する出力

HTTP/1.1 200 OK Connection: keep-alive Content-Length: 2185 content-type: application/json; charset=utf-8 x-content-type-options: nosniff x-frame-options: DENY content-disposition: inline; filename=api-result.json cache-control: private, must-revalidate, max-age=0 x-envoy-upstream-service-time: 70 X-Datacenter: SJC Accept-Ranges: bytes X-Cacheable: NO:Cache-Control=private Date: Thu, 05 May 2022 15:09:07 GMT X-Served-By: cache-wk-sjc11421-SJC, cache-tyo11922-TYO X-Cache: MISS, MISS X-Cache-Hits: 0, 0 X-Timer: S1651763347.149674,VS0,VE177 Vary: Accept-Encoding, Treat-as-Untrusted, Cookie Set-Cookie: wikia_beacon_id=YH1Gq-ALwC; domain=.fandom.com; path=/; expires=Tue, 01 Nov 2022 15:09:07 GMT; SameSite=None; Secure; Set-Cookie: wikia_session_id=zjwddvu88d; domain=.fandom.com; path=/; expires=Thu, 05 May 2022 15:39:07 GMT; SameSite=None; Secure; Set-Cookie: _b2=ZYE7xfiRcH.1651763347150; domain=.fandom.com; path=/; expires=Sat, 04 May 2024 15:09:07 GMT; SameSite=None; Secure; Set-Cookie: Geo={%22region%22:%2208%22%2C%22city%22:%22tsukuba%22%2C%22country_name%22:%22japan%22%2C%22country%22:%22JP%22%2C%22continent%22:%22AS%22}; path=/; domain=.fandom.com; SameSite=None; Secure; {"parse":{"title":"SCP-165-JP ヘイルグローブ","pageid":6907,"wikitext":{"*":"{{Cardtable| card_type = オブジェクト| sub_type = | type = Euclid| number = 165| name = SCP-165-JP ヘイルグローブ| image =420dfff8-eccc-4ee0-8092-50f2734d8d53.jpg| object_class =Euclid| attack =0| cost =2| effect_text =①このオブジェクトは財団上を離れない。<br> ②自分のターン開始時に発動する。自分または相手人事をこのオブジェクトの下に重ねる。<br> ③②の効果を発動してから5ターン後のターン終了時に発動する。このオブジェクトの下に存在する人事をdecommissionedに送る。<br>| flavor_text = 小塚研究員: 茶色じゃご不満か。<br><br>SCP-165-JP-A: 勿論! もう少し明るい色の方がいいね。<br> それとこの安っぽさが気に入らない。2000円もしないなこれは。<br>| tags =scp-jp 人間型 容器 瞬間移動 精神影響| limited = | effect_tags = |source =<span class="ui_wikidb_title">出典</span>&nbsp;JP<br><span class="ui_bottom_detail">"kasyu-maki"作 SCP-165-JP - ヘイルグローブ<br>"https://scptcgjpjwiki.gamerch.com/gamerch/external_link/?url=http%3A%2F%2Fja.scp-wiki.net%2Fscp-165-jp" http://ja.scp-wiki.net/scp-165-jp<br><br>カード公開先<br>"https://scptcgjpjwiki.gamerch.com/gamerch/external_link/?url=https%3A%2F%2Ftwitter.com%2Fkeroyu_scp%2Fstatus%2F1283263861898932224" https://twitter.com/keroyu_scp/status/1283263861898932224<br></span>}}"}}}

試したこと

curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "UTF-8");を追加したり、リクエストヘッダにcharset=utf-8を追加したりしましたが、出力に変化はありませんでした。

補足情報

OSはWindows10。
Visual Studio 2022でC++20を使用。
vcpkgを用いてcurlのver7.82.0をインストール、使用。

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

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

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

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

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

hoshi-takanori

2022/05/05 16:17

「Unicode文字」って何だろう? と思ったら、Unicode エスケープされた文字ってことですね。それも正しい JSON であり、適切に JSON をパースすれば普通の文字列になるはず…。
guest

回答1

0

ベストアンサー

レスポンスを、後述の期待する出力の項に示されるような形式で得たい。

どうしてその必要があるのでしょうか。JSONをデコードすれば、どちらも共通の結果が得られます。

投稿2022/05/06 00:09

maisumakun

総合スコア145201

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

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

keroyu

2022/05/06 13:04

nlohmnn-jsonを用いてjsonのデコードを実際に行ったところ、期待する出力に示したような結果となりました。デコードをしてもユニコード文字がそのままの形で出力されると考えていましたが、そうではないのですね。回答して頂きありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問