浅析web api的json参数校验

前言

以前api接口大家用得比较多的是表单方式传值,现在越来越流行使用json参数类型。

正文

下面从php、golang两个语言在json的使用上做一些说明。

php的处理json的两个方法名叫:

json_encode  数组转换为json字符串

json_decode  json字符串转换为数组或对象

golang官方包,Package json支持若干json的方法;

json.Marshal 

json.Unmarshal

Marshal:

名称:元帅

动词:整理、排列

例如:编列(部队) 编列json?

 

感觉两个语言的取名的侧重点不一样,php想表达的意思是编码和解码,而go想表达的意思是对数据的排列、整理成特定格式;

哪谁的表达更准确呢?

什么叫编码?

编码是信息从一种形式或格式转换为另一种形式的过程;

解码则是编码的逆过程。

按照编码的定义感觉php json方法的命名更通俗易懂!

那么json本质是个啥?

from wikipedia的定义:

JSON(JavaScript Object Notation,JavaScript对象表示法,读作/ˈdʒeɪsən/)是一种由道格拉斯·克罗克福特构想和设计、轻量级的资料交换语言,该语言以易于让人阅读的文字为基础,用来传输由属性值或者序列性的值组成的数据对象。尽管JSON是JavaScript的一个子集,但JSON是独立于语言的文本格式,目前很多编程语言都支持 JSON 格式数据的生成和解析。

json和xml的区别是啥?

JSON与XML最大的不同在于XML是一个完整的标记语言,而JSON不是。这使得XML在程序判读上需要比较多的功夫。主要的原因在于XML的设计理念与JSON不同。XML利用标记语言的特性提供了绝佳的延展性(如XPath),在数据存储,扩展及高级检索方面具备对JSON的优势,而JSON则由于比XML更加小巧,以及浏览器的内建快速解析支持,使得其更适用于网络数据传输领域。

 

web的api接口使用json参数的好处:(大前提,该api不包含上传文件;因为要上传文件还得借助表单)

1.想要对前端传递的参数进行严格的类型校验逻辑时,让前端传递json参数(json语义上可以区分字符串、数值、数组)给后端,后端通过在代码层定义的json schema对json参数进行严格数据校验逻辑(不仅json的结构要一致,键的值的类型也要一致);

2.当你的参数比较灵活时,使用form表单要提交一大堆键值对,且后端接收特定form数据和校验这个表单的代码逻辑也是只适用与这个表单;那么想象一下,当你需要整合接口,即一个add接口需要供多个类型、不同form表单进行添加数据的场景,使用json参数会比你使用表单更加灵活、便捷。(多个tab选项卡,对应多个列表,每个列表可以添加数据,数据有些许小差别,但是大致逻辑都是入库,不同点在于参数的校验的细节)

在php里面,有第三方的包(https://github.com/justinrainbow/json-schema)可以基于json schema(是用json格式书写的,用来描述JSON数据结构)的定义,来校验从客户端传递到服务器的json参数;

但是,目前在golang的web领域,还没看到有这种包的存在,官方的json包,都是可以利用Valid()校验json的合法性(即字符串是不是json字符串),但是却不能像依赖json schema的定义来细化,对json的校验,诸如:类型是否正确,是否必填;

go web方面,大家都是把json参数转换为go语言内置的struct类型变量,这就要求你得先根据json的schema定义一个对应的struct结构体类型,这点来说比php麻烦不少,毕竟php一个json_decode就可以得到一个关联数组,这或许就是弱类型解释性语言的优势。(这里不想引战,语言是个工具,每个工具有自己最适合的应用场景,有得必有失,看个人取舍)

然后验证方面都是对struct的变量,基于validator包来校验,你需要给struct的定义时,加上tag标签;

validator是依靠tag标签来进行数据的细节校验逻辑。

觉得转换json为struct的定义很麻烦?

golang json转struct的在线工具:oktools.net/json2go

据说goland2021.1.1自带这种功能,暂时没试过“Generate type from JSON”

 

下面是一段php校验json的代码:


/**
 * 概述:
 * 批量生成样本分析任务(同一份数据生成多个任务,前端只会填一个表单;不通电在于样本hash不一样)
 * 参数:
 * id [1,2,3]
 */
public function batchCreateTask()
{
    //1.获取json参数
    $taskInfo = file_get_contents('php://input');

    //json格式校验
    $jsonSchema = (object)[
        "type" => "object",
        "properties" => (object)[
            //数组的schema的定义
            "id" => (object)[
                "type" => "array",
                "items"=>(object)[
                    "type"=>"integer"
                ]
            ],
            "analysis_idea" => (object)[
                "type" => "string"
            ],
            "level" => (object)[
                "type" => "string"
            ],
            "expect_complete_time" =>(object)[
                "type" => "string",
                "default"=>""
            ]
        ],
        "required"=>[
            "id",
            "analysis_idea",
            "level"
        ]
    ];
    $this->validateJsonSchema($taskInfo,$jsonSchema);

    $taskInfoArr=json_decode($taskInfo,true);
}
 /**
     * json schema validate
     * 根据传入的json字符串和jsonScheme对象
     * 进行验证操作,如有异常就跑出异常,异常会被捕获,最终是以response的形式返回给前端报错信息
     * @param string $jsonToValidate
     * @param $jsonSchemaObj
     */
    protected function validateJsonSchema(string $jsonToValidate,$jsonSchemaObj){
        //json校验(能校验level的范围吗?)
//        $jsonSchema = (object)[
//            "type" => "object",
//            "properties" => (object)[
//                "sample_hash" => (object)[
//                    "type" => "string"
//                ],
//                "analysis_idea" => (object)[
//                    "type" => "string"
//                ],
//                "level" => (object)[
//                    "type" => "string"
//                ],
//                "expect_complete_time" =>(object)[
//                    "type" => "string",
//                    "default"=>""
//                ]
//            ],
//            "required"=>[
//                "sample_hash",
//                "analysis_idea",
//                "level",
//                "expect_complete_time"
//            ]
//        ];
        $jsonToValidateObj=json_decode($jsonToValidate);
        //如果$jsonSchema不是定义在文件中,必须用一下addSchema的方式使用!
        $schemaStorage = new SchemaStorage();
        $schemaStorage->addSchema('file://mySchema', $jsonSchemaObj);
        $validator = new Validator(new Factory($schemaStorage));
        $validator->validate($jsonToValidateObj, $jsonSchemaObj,Constraint::CHECK_MODE_ONLY_REQUIRED_DEFAULTS);

        if (!$validator->isValid()) {
            foreach ($validator->getErrors() as $error) {
                $errMsg=$error['message'];
                throw new ValidateException($errMsg);
            }
        }
}    

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值