What's the problem with "firewallrules.api.malformed_request_body“

When I requst Create firewall rules, the error message is “firewallrules.api.malformed_request_body”.

$zoneid=$rs['result'][0]['id'];
$url_add_fw="https://api.Cloudflare.com/client/v4/zones/".$zoneid."/firewall/rules";
$post = array(
    'filter' => array(
        'expression' =>'(not ip.geoip.country in {"CN"} and not ip.geoip.country in {"HK"} and not ip.geoip.country in {"MO"} and not ip.geoip.country in {"TW"})', 
    ),
    'action' => 'block',
    'description' => 'No China'
);
$post = json_encode($post,JSON_UNESCAPED_UNICODE);
echo $post;
$add_fw_rs = post_data($url_add_fw, $post, $header,8,1);
echo $add_fw_rs;

function post_data($url, $post=null, $header=array(), $timeout=8, $https=0)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_HEADER, 0);

if ($https)
{
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);  
}
if ($header)
{
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
}
if ($post)
{
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, is_array($post) ? http_build_query($post) : $post);
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$content = curl_exec($ch);
curl_close($ch);
return $content;

}