くそ。。。。json_encodeのせいだったのだ…[boringssl] boringssl_metrics_log_metric_block_invoke(151) Failed to log metrics は関係なかったのだ…

PHPで作ったapiのデータの取得を試みても何度もエラーを吐きやがる

あまりに長時間ハマったので、記録しておきたいと思います。

そう、swiftは型に厳格だったわけです。

結論からいくと、PHPのjson_encodeは、Intを勝手にStringで吐き出したりしてやがりました。

$data_sql='SELECT item_id FROM table_name limit 3';
$data=$db->prepare($data_sql);
$data->execute();
$data=$data->fetchall(PDO::FETCH_ASSOC);

$result_array=array();
$result_array["item"]=$data;
$return_json=json_encode($result_array);
header('Content-type: application/json');
echo $return_json;

////item_idはDB上、bigint

と、こんな感じで作ってたのに、何度やってもswift側がうまく取得してくれない。

こんな感じで作ってて。req_urlとかの処理ははしょるけど。

class DataList:ObservableObject{
    
    struct ResultJson:Codable{
        struct Item:Codable{
            let item_id:Int?

            
        }
        
        let item:[Item]?
    }
    
        let req = URLRequest(url:req_url)
        let session = URLSession(configuration:.default,delegate:nil,delegateQueue:OperationQueue.main)
        
        let task = session.dataTask(with:req,completionHandler:{
            (data,response,error) in
           
            session.finishTasksAndInvalidate()
            
            do{
                let decoder = JSONDecoder()
                let json = try decoder.decode(ResultJson.self,from:data!)
  
                print(json)
                
            }catch{
                print("エラー発生")
                
                
            }
            
        })
        
        task.resume()

で、よく見たら、よーーーくみたら、PHPで作ったapiのデータ、こんな感じだった

{"item":[{"item_id":"5723651"},{"item_id":"7161644"},{"item_id":"7161645"}]}

DBの型に基づいてうまくやってくれると思ったら、Stringになってやがる。。

なので、API側を以下に修正

$return_json=json_encode($result_array);

から

$return_json=json_encode($result_array,JSON_NUMERIC_CHECK);

これでうまくはいくんだけど、でも完全じゃない。例えば乱数とか出して数字ばかりだったからだといって、Intにされると、同じカラムのはずなのに、値によって型を変えてしまう可能性があるのだ。



だから、明示的にですが

$data["item_id"]=(int)$d["item_id"]

みたいな感じでバカ丁寧に配列を作って、json_encodeするのがいいらしい。


もうこれで忘れないぞ!

コメント