内容纲要
背景
项目中遇到一个使用场景:服务端要保存用户上传的json格式示例,但是服务端针对这个json格式示例有大小限制,比如1KB,超过这个大小后服务端就不能正常保存了。此时用户正好手里有个比较大(>1KB)的json示例,他要想将这个示例正常保存可以进行两种不同操作:
- 手动去裁剪这个json字符串;
- 通过智能的方式自动将一些重复且不必要的数据删除掉,以达到json裁剪的目的
显然,针对第一种方式不太明智,那我们如果采用第二种方式的话,又该怎么做呢?
操刀
在Go里面,我们引用官方标准库encoding/json
对json进行序列化和反序列化时用的最多的也是下面的两个方法:
func Unmarshal(data []byte, v interface{}) error
func Marshal(v interface{}) ([]byte, error)
注意里面的入参interface类型参数,第一个是将data里面数据反序列化到v中,第二个是将v中参数序列化成json字符串。而我们json格式对象常用的格式基本上都是下面这两种类型的:
[
xxx,xxx,...
]
和
{
xxx:ooo,...
}
我们正好可以分别用[]interface{}
表示数组和map[string]interface{}
表示大对象,然后顺理成章的采用递归的方式,循环处理里面的数据。代码如下:
func knife(itf interface{}) interface{} {
var t interface{}
if _, ok := itf.(string); ok {
t = ""
} else if im, ok := itf.(map[string]interface{}); ok {
for k := range im {
im[k] = knife(im[k])
}
t = im
} else if ia, ok := itf.([]interface{}); ok {
if len(ia) != 0 {
t = []interface{}{knife(ia[0])}
} else {
t = ia
}
} else {
t = itf
}
return t
}
上面knife方法实现的机制为:
- 采用递归循环判断传递进来的对象类型,如果为map对象则对map中每个key所对应的value值进行循环判断,如果为数组对象则直接选取数组对象中的第一个元素;
- 上面例子中奖所有string类型value全都重置成了空字符串
然后达到了裁剪json的目的,且不损失json格式完整性。
注:
- 以上方式主要目的是给你们一个启迪作用,具体要达到怎样的效果,可以根据实际也许需求来执行,比如要在一个未知的json里面新增固定key:value、字符串批量替换等骚操作都可以采用这种方式稍微魔改一下就行了。
文章评论