上篇文章《Golang中如何校验字符串是否为JSON格局?》首要讲解了运用json.Valid校验字符串是否JSON格局的运用办法,本文来分析一下json.Valid办法的源码

json.Valid办法源码

json.Valid办法界说:

// Valid reports whether data is a valid JSON encoding.
func Valid(data []byte) bool {
	scan := newScanner()
	defer freeScanner(scan)
	return checkValid(data, scan) == nil
}

scan := newScanner() 获取一个 scanner 类型的对象,要害的是checkValid办法,checkValid源码如下:

// checkValid verifies that data is valid JSON-encoded data.
// scan is passed in for use by checkValid to avoid an allocation.
func checkValid(data []byte, scan *scanner) error {
	scan.reset()
	for _, c := range data {
		scan.bytes++
		if scan.step(scan, c) == scanError {
			return scan.err
		}
	}
	if scan.eof() == scanError {
		return scan.err
	}
	return nil
}

首先调用了scan.reset(),首要是初始化scanner要害字段,如下:

s.step = stateBeginValue
s.parseState = s.parseState[0:0]
s.err = nil
s.endTop = false

然后就是通过遍历要校验的数据,运用状态机方式做判别。

运用一个示例来看检测进程

接下来以 {“a”:”b”} 为例,来看下整个的判别进程:

  1. scan.reset()执行后将将step赋值为stateBeginValue;
  2. 首先判别“{”,运用stateBeginValue办法进行判别,发现是,将step赋值为stateBeginStringOrEmpty,执行pushParseState往parseState追加表明是key的值0;
  3. 接下来判别“””,运用stateBeginStringOrEmpty办法进行判别,紧接着运用stateBeginString办法进行判别,发现是,将step赋值为stateInString;
  4. 接下来判别“a”,运用stateInString办法进行判别,发现是,持续遍历;
  5. 接下来判别“””,运用stateInString办法进行判别,发现是,将step赋值为stateEndValue;
  6. 接下来判别“:”,运用stateEndValue办法进行判别,看parseState最后一个值,发现是key部分,检测到时“:”,将parseState最后一个值置为value部分标识,将step赋值为stateBeginValue;
  7. 接下来判别“””,运用stateBeginValue办法进行判别,发现是,将step赋值为stateInString
  8. 接下来判别“b”,运用stateInString办法进行判别,发现是,持续往下遍历;
  9. 接下来判别“””,运用stateInString办法进行判别,发现是,将step赋值为stateEndValue;
  10. 接下来判别“}”,运用stateEndValue办法进行判别,看parseState最后一个值,发现是value部分,检测到了“}”,如果parseStat长度为0,step赋值stateEndTop,如果不为0,将step赋值为stateEndValue,检测结束,回来成果。

小结

大家能够结合源码和本文来自己体会一下整个的检测进程。json.Valid办法会把例如123、true、false、null等也认为是json编码,这可能不是大家在开发进程中想要的成果,所以下一篇文章会介绍根据json.Valid办法改造后的办法,完美得实现json格局校验。