1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【PowerShell】でDBにPOSTした際に文字化けする問題の解決方法

Posted at

はじめに

個人開発をしている大学生やまいです。現在は読書家向けSNSを開発しており、本記事もそれの一環です。今後も本開発で学んだことを発信していくため、似たようなものを作りたいという方は追ってください。
この世にはcurlInvoke-RestMethodPOSTした際に日本語が文字化けするという問題があります。本記事ではその解決法を紹介します。

環境

OS
Windows11
Go
1.23.2 windows/amd64
PostgreSQL
1.5.11
PowerShell
7.2.24

発生した問題

一番最初に実行していたコマンドはこちらです。これではPOSTしたBookTitleとContentが???になってしまいます。

Invoke-RestMethod -Uri "http://localhost:8080/reviews" -Method Post -Headers @{"Content-Type"="application/json"} -Body (@{ BookTitle="吾輩は猫である"; Content="おもろかった"} | ConvertTo-Json -Depth 10 -Compress)

インサートした際の出力

ID BookTitle Content CreatedAt
-- --------- ------- ---------
 8 ???????   ??????  2025/03/06 13:52:32

今回のシステムではPowerShellからリクエストを送信→Goのプログラムがそれを取得しDBに登録という形でインサートしています。

行った対策

1.SQLから直接INSERT

まずはどこで文字化けが起きているのか特定するためにPowerShellから直接DBにインサートします。

docker exec -it book_review_db psql -U user -d book_review -c "INSERT INTO reviews (BookTitle, Content) VALUES ('吾輩は猫である', 'おもろかった');"

すると、文字化けせずにインサートすることができました。

2.Go側で受け取ったJSONデータを確認

前節でPostgreSQL側の設定が正しく、PowerShellからGoにリクエストを送信している部分かGoのプログラムがDBに登録している部分のどちらかで文字化けが起こっていることが確認できました。
POSTメソッドを受け取るGoのプログラムに受け取ったJSONデータを確認するプログラムを追加します。

controllers/reviews.go
package controllers

import (
	"bytes"
	"dokusyo/backend/database"
	"dokusyo/backend/models"
	"fmt"
	"io"
	"net/http"

	"github.com/gin-gonic/gin"
)

// 感想一覧を取得
func GetReviews(c *gin.Context) {
    var reviews []models.Review
    database.DB.Find(&reviews)
    c.JSON(http.StatusOK, reviews)
}

// 新しい感想を投稿
func CreateReview(c *gin.Context) {
    var review models.Review

    // クライアントから送信された JSON を確認
    jsonData, _ := c.GetRawData()
    fmt.Println("Received JSON:", string(jsonData))

    // 読み取ったデータを元にリクエストのボディを再セット
    c.Request.Body = io.NopCloser(bytes.NewBuffer(jsonData))

    if err := c.ShouldBindJSON(&review); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    // Go 内部で受け取ったデータを確認
    fmt.Println("Parsed Review:", review.BookTitle, review.Content)

    database.DB.Create(&review)
    c.JSON(http.StatusCreated, review)
}

このプログラムににより、Go側のRecieved JSON:で????が表示、つまりPowerShellから送信した時点でJSONのエンコーディングが壊れていることが分かった。

3.ConvertTo-Jsonを使用

コマンドにConvertTo-Jsonオプションを追加し実行。

Invoke-RestMethod -Uri "http://localhost:8080/reviews" -Method Post -Headers @{"Content-Type"="application/json; charset=utf-8"} -Body ($(@{ BookTitle="吾輩は猫である"; Content="おもろかった"} | ConvertTo-Json -Depth 10 -Compress))

結果変わらず、エンコーディングは崩れたまま?????が保存された

4.UTF-8にエンコードして送信(解決)

最初にbody部分を定義、その後エンコードして送信する。

$body = '{ "BookTitle": "吾輩は猫である", "Content": "おもろかった" }';
$utf8Body = [System.Text.Encoding]::UTF8.GetBytes($body);
Invoke-RestMethod -Uri "http://localhost:8080/reviews" -Method Post -Headers @{"Content-Type"="application/json; charset=utf-8"} -Body $utf8Body

これによってエンコーディングは崩れずインサートすることができた。

わかったこと

解決法として、先にUTF-8にエンコードしてから送信すると文字崩れが起きないことが分かった。
MicrosoftのInvoke-RestMethodページを参照したところ、PowerShell7.4以降ではUTF-8に設定されていると書かれている。そこでPowerShellのバージョンを確認してみると...

$PSVersionTable.PSVersion
Major  Minor  Patch  PreReleaseLabel BuildLabel
-----  -----  -----  --------------- ----------
7      2      24

コレガゲンインデスネスミマセン

なお、curlコマンドを実行しても文字化けせずにインサートすることができる。
-X POSTを使うパターン

curl.exe --data '"{\"BookTitle\": \"吾輩は猫である\", \"Content\": \"おもろかった\"}"' --verbose --request POST --url "http://localhost:8080/reviews"

--jsonを使うパターン

curl --json '"{\"BookTitle\": \"吾輩は猫である\", \"Content\": \"おもろかった\"}"' http://localhost:8080/reviews

参考文献

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?