简单生成json对象 和 解析json
坐在无聊便写了一个 欢迎围观
生成json
var stringify = function (argument) {
var result = '{';
if (argument instanceof Object) {
for (let attr in argument) {
result += '"' + attr + '":';
if (argument[attr] instanceof Object) {
result += stringify(argument[attr])
} else {
result += argument[attr];
}
result += ","
}
//去掉最后一个 逗号
result = result.substring(0, result.length - 1)
result += "}"
return result
} else {
throw "must be an object"
}
}
var json = stringify({attr1: 11, attr2: {attr3: 33, attr4: 44, attr5: {attr6: 66, attr7: 77, attr8:88}}})
var parseJson = JSON.parse(json)
console.log(parseJson)
解析json
//这个是用来做的对称符号的 比如 'aaa { {aaa{ a}}} {aaaa}'
//找到 第一个 { 对应的 } 位置
function findSymmetricSymbol(targetString, startIndex, leftSymbol, rightSymbol) {
if (targetString.charAt(startIndex) !== leftSymbol) {
throw 'argument error'
}
var stack = [] // 这个栈是用来 寻找 左符号的 对应的 右符号 不断入栈 出栈
for (var i = startIndex; i < targetString.length; i++) {
if (targetString[i] === leftSymbol)
stack.push(leftSymbol)
else if (targetString[i] === rightSymbol) {
stack.pop()
if (stack.length === 0) {
return i
}
}
}
return -1
}
//console.log(findSymmetricSymbol("{{aaaaa{{aaaaa{{{aaa}}aa}}aa}}a}", 7, '{', '}'))
var parse = function(argument) {
if (typeof (argument) !== "string") {
throw "must be a string"
}
//去掉所有的空格
argument = argument.replace(/\s/g, "")
return function innerParse(argument) {
//第一个括号对于的对象 每个括号生成一个对象
var result = {}
var tempKey = null
//从 1 开始 0固定为 { 即 result对象
for (var i = 1; i < argument.length; i++) {
//取key
if (argument[i] === '"') {
var keyStartIndex = i
var keyEndIndex = argument.indexOf('"', i + 1)
tempKey = argument.substring(keyStartIndex + 1, keyEndIndex)
i = keyEndIndex
}
if (argument[i] === ':') {
//取value
if (argument[i + 1] === '[') {
var tempArray = []
var rightMiddleBracket = findSymmetricSymbol(argument, i + 1, '[', ']')
var tempArrayString = argument.substring()
}
if (argument[i + 1] === '{') {
//递归 生成对象
var leftBracket = i + 1
var rightBracket = findSymmetricSymbol(argument, i + 1, '{', '}')
childrenObjString = argument.substring(leftBracket, rightBracket + 1)
result[tempKey] = innerParse(childrenObjString)
i = rightBracket
} else {
var valueEndIndex = argument.indexOf(',', i)
//防止末尾没有 , 的情况
if (valueEndIndex != -1) {
result[tempKey] = argument.substring(i + 1, valueEndIndex)
i = valueEndIndex
} else {
//末尾 没有 逗号
result[tempKey] = argument.substring(i + 1, argument.length - 1)
i = argument.length
}
}
}
}
return result
}(argument)
}
console.log(parse('{"aa" :{"bb":11, "ee": {"ff":33, "gg":44}}, "cc" : {"dd":22, "ee": {"ff":33}}}'))
// console.log(parse(json))
解析json新版本
function findSymmetricSymbol(targetString, startIndex, leftSymbol, rightSymbol) {
if (targetString.charAt(startIndex) !== leftSymbol) {
throw 'argument error'
}
var stack = [] // 这个栈是用来 寻找 左符号的 对应的 右符号 不断入栈 出栈
for (var i = startIndex; i < targetString.length; i++) {
if (targetString[i] === leftSymbol)
stack.push(leftSymbol)
else if (targetString[i] === rightSymbol) {
stack.pop()
if (stack.length === 0) {
return i
}
}
}
return -1
}
// console.log('{{aaaaa{{aaaaa{{{aaa}}aa}}aa}}a}'.length)
// console.log(findSymmetricSymbol("{{aaaaa{{aaaaa{{{aaa}}aa}}aa}}a}", 7, '{', '}'))
function parseSimpleJson(argument) {
var result = {}
argument = argument.trim()
argument = argument.substring(1, argument.length - 1) //去掉{ }
var allKeyValueArray = argument.split(',')
allKeyValueArray.forEach(function (element) {
singleKeyAndValue = element.split(':')
result[singleKeyAndValue[0]] =singleKeyAndValue[1]
})
return result
}
/*
算法思想: 把复杂的json简单话
最简单的形式: {"aa": 11, "bb": 22}
混杂形式 {"aa": 11, "bb": {"aa": 11}}
流程为 混杂形式----转变成 {"aa": 11, "bb": token} ---->token记录在map中 map[token] = '{"aa":11}'
把 {"aa": 11, "bb": token} 利用parseSimpleJson 转成对象
在依次遍历 这个对象里面的属性, 如果map[attr] 存在的话,就递归 map[token] 得到这个对象
*/
var parse = function(argument) {
//去掉所有的空格
argument = argument.replace(/\s/g, "")
map = {} //全局的map对象
id = 0 //map 全局id
return function innerParse(argument) {
var result = null
var currentIndex = 1 //跨过第一个 {
while(currentIndex < argument.length) {
if (argument[currentIndex] === '{') {
var right = findSymmetricSymbol(argument, currentIndex, '{', '}')
var subStr = argument.substring(currentIndex, right + 1)
var uuid = (id++) + ''
map[uuid] = subStr
argument = argument.substring(0, currentIndex) + uuid + argument.substring(right + 1)
currentIndex += uuid.length
} else {
currentIndex++
}
}
result = parseSimpleJson(argument)
// console.log(map)
for (var key in result) {
var mapKEY = result[key]
if (map[mapKEY] != null) {
// console.log(map[key])
result[key] = innerParse(map[mapKEY])
}
}
return result
}(argument)
}
var testJ = '{"aa": 11, "bb":{" aa":11, "bb":22, "cc": {"dd": 55}}, "ff":{"dd": 66}}';
console.log(parse(testJ)['"bb"'])
完整数组版
//解析成 json
var stringify = function (argument) {
var result = '{';
if (argument instanceof Object) {
for (let attr in argument) {
result += '"' + attr + '":';
if (argument[attr] instanceof Object) {
if (argument[attr] instanceof Array) {
let tempArray = "["
argument[attr].forEach(function(element) {
//防止循环引用
if (argument === element) {
throw "Converting circular structure to JSON"
}
if (element instanceof Object) {
tempArray += stringify(element)
} else {
tempArray += element
}
tempArray += ","
})
tempArray = tempArray.substring(0, tempArray.length - 1)
tempArray += "]"
result += tempArray
} else {
if (argument === argument[attr]) {
throw "Converting circular structure to JSON"
}
result += stringify(argument[attr])
}
} else {
result += argument[attr];
}
result += ","
}
//去掉最后一个 逗号
result = result.substring(0, result.length - 1)
result += "}"
return result
} else {
throw "must be an object"
}
}
// 生成json对象
/*
算法思想: 把复杂的json简单话
最简单的形式: {"aa": 11, "bb": 22}
混杂形式 {"aa": 11, "bb": {"aa": 11}, "cc":[11,22,{"aa":11}, 11]}
混杂形式有 对象 数组
流程为 混杂形式----转变成 {"aa": 11, "bb": token1, "cc": token2}
--->token1, token2记录在map中 map[token1] = '{"aa":11}' map[token2] = [11,22,{"aa":11}, 11]
把 {"aa": 11, "bb": token1, "cc":token2} 利用parseSimpleJson 转成对象
在依次遍历 这个对象里面的属性, 如果map[attr] 存在的话,
如果 map[token/attr]为对象形式的字符串 就直接递归 parse
如果 map[token/attr]为数组 就预处理数组字符串,数组字符变成 [11, 22, token3, 11]的数组对象
然后再把 token3 变成 parse(token3)即可
*/
function findSymmetricSymbol(targetString, startIndex, leftSymbol, rightSymbol) {
if (targetString.charAt(startIndex) !== leftSymbol) {
throw 'argument error'
}
var stack = [] // 这个栈是用来 寻找 左符号的 对应的 右符号 不断入栈 出栈
for (var i = startIndex; i < targetString.length; i++) {
if (targetString[i] === leftSymbol)
stack.push(leftSymbol)
else if (targetString[i] === rightSymbol) {
stack.pop()
if (stack.length === 0) {
return i
}
}
}
return -1
}
// console.log('{{aaaaa{{aaaaa{{{aaa}}aa}}aa}}a}'.length)
// console.log(findSymmetricSymbol("{{aaaaa{{aaaaa{{{aaa}}aa}}aa}}a}", 7, '{', '}'))
function parseSimpleJson(argument) {
var result = {}
argument = argument.trim()
argument = argument.substring(1, argument.length - 1) //去掉{ }
var allKeyValueArray = argument.split(',')
allKeyValueArray.forEach(function (element) {
singleKeyAndValue = element.split(':')
result[singleKeyAndValue[0]] =singleKeyAndValue[1]
})
return result
}
/*
这个是对 数组进行预处理, 生成一个
带token的 数组对象
而且token 全放入 map中 引用map
idObj是为了全局的唯一id做准备 引用传入 idObj = {id: num, prefix:_*_, suffix:_*_}
*/
function preprocessJsonArray(arrayString, map, idObj) {
var result = null
arrayString = arrayString.substring(1, arrayString.length - 1) //去掉[ ]
var currentIndex = 0
while(currentIndex < arrayString.length) {
if (arrayString[currentIndex] === '{') {
var right = findSymmetricSymbol(arrayString, currentIndex, '{', '}')
var subStr = arrayString.substring(currentIndex, right + 1)
var uuid = idObj.prefix + (idObj.id++) + idObj.suffix
map[uuid] = subStr
arrayString = arrayString.substring(0, currentIndex) + uuid + arrayString.substring(right + 1)
currentIndex += uuid.length
} else {
currentIndex++
}
}
result = arrayString.split(',')
return result
}
// preprocessJsonArray('["aa", "bb", {"aa":11}, "cc", {"dd":22}]', {}, {"id": 0, "prefix":"_*_", "suffix":"_*_"})
/**
对 json对象的预处理
argument 为 json对象字符串 {"aa":11...}
map 为全局的存储 对象
idObj 是为了生成 uuid的
*/
function preprocessJsonObject(argument, map, idObj) {
var result = null
var currentIndex = 1 //跨过第一个 {
while(currentIndex < argument.length) {
if (argument[currentIndex] === '{' || argument[currentIndex] === '[') {
var leftSymbol = '{'
var rightSymbol = '}'
if (argument[currentIndex] === '[') {
leftSymbol = '['
rightSymbol = ']'
}
var right = findSymmetricSymbol(argument, currentIndex, leftSymbol, rightSymbol)
var subStr = argument.substring(currentIndex, right + 1)
var uuid = idObj.prefix + (idObj.id++) + idObj.suffix
map[uuid] = subStr
argument = argument.substring(0, currentIndex) + uuid + argument.substring(right + 1)
currentIndex += uuid.length
} else {
currentIndex++
}
}
result = parseSimpleJson(argument)
return result
}
// preprocessJsonObject('{"aa":11, "bb":22, "dd":{"aa":11}, tt:"cc", ff:{"dd":22}}', {}, {"id": 0, "prefix":"_*_", "suffix":"_*_"})
// 核心代码
var parse = function(argument) {
//去掉所有的空格
argument = argument.replace(/\s/g, "")
map = {} //全局的map对象
idObj = {"id": 0, "prefix":"_*_", "suffix":"_*_"} //map 为了生成map全局id
return function innerParse(argument) {
var result = preprocessJsonObject(argument, map, idObj)
// console.log(result)
for (var key in result) {
var mapKEY = result[key]
//只能为 数组[] 或者 对象{}的情况
if (map[mapKEY] != null) {
//区别对象和数组的情况
if (map[mapKEY].startsWith('{')) {
result[key] = innerParse(map[mapKEY])
} else {
//处理数组的情况
tempArrayObj = preprocessJsonArray(map[mapKEY], map, idObj)
for (var i = 0; i < tempArrayObj.length; i++) {
if (map[tempArrayObj[i]] != null) {
tempArrayObj[i] = innerParse(map[tempArrayObj[i]])
}
}
result[key] = tempArrayObj
}
}
}
return result
}(argument)
}
// var testJ = '{"aa": 11, "bb":{" aa":11, "bb":22, "cc": {"dd": 55}}, "gg":[{"aa":11, "bb":22}, "aa", {"cc":11}], "ff":{"dd": 66}}';
// console.log(parse(testJ))
var testObj = { "aa": 11,
"bb":["aa", {"aa":11}, 11, 33],
"cc":{"dd": 22, "ee":{"aa":11, "bb":22}},
"dd": 11}
var jsonString = stringify(testObj)
console.log("stringify: ",jsonString)
console.log('-----------------------')
console.log('parse: ', parse(jsonString))
10 回复
补充一个循环引用的实现,circular-json 更有意思
@i5ting 循环的有空在想想 ,又写了一个解析, 谢谢狼叔的回复啊
代码看起来风格有点问题, 不知道是不是编辑器的原因
@yongningfu 感觉是markdown
没弄好吧,缩进多了点,整体格式在的
有几个问题:
- json 里面是可以有数组的
- 生成 json 的方法里面,
argument[attr]
如果是字符串,需要加上引号 - 生成 json 的方法里面,万一传入的 argument 包含循环引用怎么办
@xcatliu 居然是mobi.css大神, 你的mobi.css 我很喜欢啊, 第一个问题的话,其实 暂时不做数组的, 第二个问题的话,其实我一开始是没考虑做类型转化的,第三个问题的话,我感觉你可能是想说无限递归的情况,但是能简单的举个例子么? 还有我刚刚写了一个解析json的新思路,这个思路比之前遍历递归要简单的多, 而且核心代码 不过 30行,大神能否看看。 感谢大神回复
@xcatliu 具体的算法思想我在里面有写了的
@xcatliu @i5ting @DevinXian 添加了完整的数组版
@xcatliu 测了一下标准库,发现它对于循环引用的问题是直接抛出异常,所以我也自己修改为抛出异常了。 字符串问题后面再抽空解决一下