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

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

ただいまの
回答率

90.01%

PHP側で、全角の文字データを含んだJsonをデコードすると空文字になります

解決済

回答 2

投稿

  • 評価
  • クリップ 2
  • VIEW 2,014

aiueoao

score 91

前提・実現したいこと

Unity3D(c#)にて、inputfieldでユーザ入力を受け取りJsonUtility.ToJsonでJSON 形式に変換後、それをサーバー(PHP)へ送りデコードしてデータベースに保存したいのですが、デコード時にユーザ入力全角文字(2バイト文字?)が空文字になります。全角文字が消えないようにするにはどうすればいいのでしょうか?

全角と半角英字の混合文だと半角英字のみ残ります (例: aあ  [decode]→ a)

PHPのデコード部分に問題があると思い、いろいろと調べてみましたが解決に至りませんでした。
お力添えお願いいたします

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

デコード時にBOMを除く処理を入れないと json_last_error() で
Control character error, possibly incorrectly encoded\r+ が出る状態です

該当のソースコード

//Unity3D側
using UnityEngine;
using System.Collections;
using System;

public class DB_Test : MonoBehaviour {

    public InputField inp;      //ユーザ入力のためのinputfield
    const string LOCALDOMAIN = "localhost";
    string m_url = "http://" + LOCALDOMAIN + "/phptest.php";

    //jsonにして phpへ渡すクラス
    [Serializable]
    class MyJsonClass
    {
        public string mydata;            //ユーザ入力をここへいれる
    }

    //ボタンイベントで開始
    public void OnButton()
    {
        try
        {
            WWWForm form = new WWWForm();      //データ送信準備

            MyJsonClass gs = new MyJsonClass();
            gs.mydata= inp.text;        //inputfieldの値を phpへ渡すクラスのメンバー変数に代入

            string str = JsonUtility.ToJson(gs);    //クラスをJson形式に変換
            form.AddField("post", str);
            WWW result = new WWW(m_url, form);      // Web にシンプルにアクセスします
        }catch(Exception e)
        {
            Debug.Log("error"+e.ToString());
        }
    }
}
// サーバー側
<?php

// DB接続処理.
require_once dirname(__FILE__) . '/db_Conf.php';
// 出力形式の設定  JSON形式で送信
header( 'Content-type: application/json; charset=UTF-8' );


    //JSON文字列をデコード(復号)するユーザ定義関数       引数にJson文字列
    function deco($js)
    {
        //BOMをとってデコード
        $obj=json_decode(preg_replace('/[\x00-\x1F\x80-\xFF]/', '',$js),false);

        if (json_last_error() === JSON_ERROR_NONE) {
            return $obj;
        }else {
            exit;       // エラーがあれば終了
            }
    }

    $db = getDb();              //DBへの接続を確立
    $jsondata=$_POST['post'];   //簡単のために直接代入
    $obj=deco($jsondata);       //オブジェクト型でデコード

    //----------DB登録----------
    $stt=$db->prepare('insert into u2 (mydata) values (:data)');
    $stt->bindvalue(':data',$obj->mydata);
    $stt->execute();    //実行

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

Unity3d 5.3.5f1 (64bit)
PHP 7.0.8
phpエディタ Visual Studio code (UTF-8)
db PostgreSQL

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

preg_replace で文字列を置換する際には u 修飾子が必要かどうかを確認しましょう。
PCRE では u 修飾子がついていない場合はバイト単位、ついている場合は文字単位で処理されます。マッチを行う際にはほとんど問題になりませんが、置換の際には気をつけなれけばなりません。

<?php
// u 修飾子なしの場合
preg_replace('/[\x00-\x1F\x80-\xFF]/', '', 'あいうえお'); // => ''

// u 修飾子ありの場合
preg_replace('/[\x00-\x1F\x80-\xFF]/u', '', 'あいうえお'); // => 'あいうえお'

今回の処理の目的は BOM を削除することなのでバイト単位で処理してしまうと日本語の範囲の文字は消えてしまうため、u 修飾子をつける必要があります。

参考:
PHP: 正規表現パターンに使用可能な修飾子 - Manual

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/10/14 11:21

    回答ありがとうございます。教えて頂いた通りにやったらできました!
    正規表現パターンの修飾子は失念してました。

    キャンセル

0

まず関数が受け取った直後の $js、 正規表現を通した後の $js をデバッグ出力して内容を確認してはどうでしょうか?
見た感じ正規表現でBOMだけでなくASCII文字以外の全ての文字を削除してしまっている気がします。

 Control character error, possibly incorrectly encoded\r+

このエラーは文字通り改行コードの問題ではないかと。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/10/14 11:27

    回答ありがとうございます。
    仰られる様な確認方法を思いつきませんでした。大変参考になります。

    キャンセル

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

  • ただいまの回答率 90.01%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る