web-dev-qa-db-ja.com

UTF-8でエンコードされたCurl JSON

重要な注意:私はCygwinを使用しています


curlを使用してサーバーに送信する前に変更したファイルからJSONを取得します。サーバーがJSONを受信するとき、すべての特殊文字(アクセントなど)は十分にエンコードされていません。これは、JSONが送信される前にUTF-8でエンコードされていなかったためと思われますが、変換できませんでした。

これがコードです:

sed -i 's/\r//g' $file
fileContent=`cat $file`

result=$(jq -c -j ".docs[$docIndex] + { \"_rev\": \"$rev\" }"<<<"$fileContent")            result="{\"docs\":[$result]}"

result=$result | sed 's/\r//g'
result=$result | iconv -t "UTF-8"
s=$(curl -H "Content-Type: application/json; charset=UTF-8" -H "Cache-Control: no-cache" -d "$result" $2/$3/_bulk_docs --silent)

私のbashスクリプトとJSONファイルはどちらもUTF-8でエンコードされています。私のLANG変数はUTF-8のようです。私はこれで確認しました:[[ $LANG =~ UTF-8$ ]] && echo "Uses UTF-8 encoding.."

何か案が?


更新

完全なスクリプトは次のとおりです。

#!/bin/bash

# $1 = directory containing JSON files
# $2 = server url (+ port)
# $3 = database name

#Loop on every file of the given directory
for file in "$1"/*; do

    #Try to insert every document of a specific JSON file and retrieve their status (200 = OK; 409 = conflict)
    allStatus=$(curl -H "Content-Type: application/json" -H "Cache-Control: no-cache" --data-binary "@$file" $2/$3/_bulk_docs --silent | jq '.[] |.status' | tr -d '\r')
    docIndex=0

    #Loop on every status (one status = one document)
    while IFS=' ' read -ra statusArray; do
      for status in "${statusArray[@]}"; do

        #Remove unwanted windows characters of the file
        sed -i 's/\r//g' $file
        fileContent=`cat $file`

        #Retrieve the id of the current document
        id=`jq -r -j ".docs[$docIndex]._id"<<<"$fileContent" | tr -d '\r'`

        if [ "$status" = "409" ]
        then 
            #Retrieve the revision of the current document and add it to the document 
            rev=$(curl -X GET --header 'Accept: application/json' $2/$3/$id?revs=true --silent | jq -r -j '._rev' | tr -d '\r')
            result=$(jq -c -j ".docs[$docIndex] + { \"_rev\": \"$rev\" }"<<<"$fileContent")

            #Wrap the document inside {"docs":[]}
            result="{\"docs\":[$result]}"

            #Remove unwanted windows characters before sending the document (again)
            result=$result | sed 's/\r//g'
            result=$result | iconv -t "UTF-8"
            s=$(curl -H "Content-Type: application/json; charset=UTF-8" -H "Cache-Control: no-cache" -d "$result" $2/$3/_bulk_docs --silent)

            #Echo result
            echo $s
        else
          #Status should be 200.
          echo 'status: '$status ' - ' $id
        fi

        docIndex=$((docIndex+1))

      done
    done <<< "$allStatus"
done

このスクリプトは、NoSQLデータベース内のドキュメントをアップサートすることを目的としています。最初に挿入を試み、失敗した場合は、ドキュメントのプロパティ(リビジョン)を取得します。それに追加してから、もう一度再試行します。

私はこのスクリプトが改善されることを知っていますが、これは私の最初のbashスクリプトであり、本番環境では使用されません(テストのみなど)。

4
MHogge

CygwinのBashでこれを使用するには、少なくともPython 2.7がインストールされている必要があります。

utf8_result="$(echo "$result" | python -c "import sys;[sys.stdout.write((i).decode('utf-8')) for i in sys.stdin]")"
1
rubynorails

部分的な答え:

man curlによると、-dまたは--dataは、コンテンツタイプapplication/x-www-form-urlencodedを使用してPOSTを実行し、--data-asciiと同等です。ヘッダーをオーバーライドしようとすると、これが変わるとは思いません。 standard によると、urlencodingの文字セットはフォーム要素に依存しますが、ここでは完全に欠落しています。

スクリプトを正しく理解していれば、$resultはUTF-8であり、URLエンコードされていません。したがって、おそらく--data-urlencode(詳細についてはman curlを参照)を使用し、UTF-8を正しくエンコードすることを期待するか、代わりに--formを使用する必要があります。これはより柔軟で、文字セットフィールドを含めることができます。

したがって、主な問題は、標準がエンコードを規定する方法にあるようです。これは、(少なくとも私にとって)理解するのが十分に困難です。多分あなたはstackoverflowでより良い答えを得ることができます。

1
dirkt