blob: 60fb71b170ee1a36ad07ce925fa2838b30a6f1d6 [file] [log] [blame]
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package util
import (
"errors"
)
//TOKEN_TYPE json string's token type
type TOKEN_TYPE byte
const (
//STRING string
STRING TOKEN_TYPE = iota
//NUMBER number
NUMBER
//START_OBJ start object
START_OBJ
//END_OBJ end object
END_OBJ
//COMMA comma
COMMA
//COLON colon
COLON
)
type token struct {
tokenType TOKEN_TYPE
tokenValue string
}
////{"offsetTable":{{"brokerName":"broker-b","queueId":122222,"topic":"GoLang"}:9420,{"brokerName":"broker-b","queueId":2,"topic":"GoLang"}:9184,{"brokerName":"broker-b","queueId":1,"topic":"GoLang"}:9260,{"brokerName":"broker-b","queueId":3,"topic":"GoLang"}:9139}}
type parseInfo struct {
startObjCount int
// 0 begin 1 key 2 value
readType int
nowKey string
nowValue string
}
//GetKvStringMap convert json string to map[string]string
func GetKvStringMap(str string) (kvMap map[string]string, err error) {
var tokenList []token
tokenList, err = parseTokenList(str)
kvMap = map[string]string{}
currentParseInfo := &parseInfo{
startObjCount: 0,
readType: 0,
nowKey: "",
nowValue: "",
}
for i := 0; i < len(tokenList); i++ {
nowToken := &tokenList[i]
if nowToken.tokenType == START_OBJ {
currentParseInfo.startObjCount++
}
if nowToken.tokenType == END_OBJ {
currentParseInfo.startObjCount--
}
if currentParseInfo.readType == 0 {
if nowToken.tokenType != START_OBJ {
err = errors.New("json not start with {")
return
}
currentParseInfo.readType = 1
} else if currentParseInfo.readType == 1 {
parseKey(currentParseInfo, nowToken)
} else if currentParseInfo.readType == 2 {
var k, v string
k, v = parseValue(currentParseInfo, nowToken)
if len(k) > 0 {
kvMap[k] = v
}
} else {
err = errors.New("this is a bug")
return
}
}
if len(currentParseInfo.nowKey) > 0 {
kvMap[currentParseInfo.nowKey] = currentParseInfo.nowValue
}
return
}
func parseValue(info *parseInfo, nowToken *token) (key, value string) {
if nowToken.tokenType == COMMA { // , split kv pair
if info.startObjCount == 1 {
key = info.nowKey
value = info.nowValue
info.nowKey = ""
info.nowValue = ""
info.readType = 1
return
}
}
if nowToken.tokenType == STRING {
info.nowValue = info.nowValue + "\"" + nowToken.tokenValue + "\""
} else {
if info.startObjCount > 0 { //use less end }
info.nowValue = info.nowValue + nowToken.tokenValue
}
}
return
}
func parseKey(info *parseInfo, nowToken *token) {
if nowToken.tokenType == COLON { //: split k and v
if info.startObjCount == 1 {
info.readType = 2
return
}
}
if nowToken.tokenType == STRING {
info.nowKey = info.nowKey + "\"" + nowToken.tokenValue + "\""
} else {
info.nowKey = info.nowKey + nowToken.tokenValue
}
return
}
func parseTokenList(str string) (tokenList []token, err error) {
for i := 0; i < len(str); i++ {
c := str[i]
token := token{}
switch c {
case '{':
token.tokenType = START_OBJ
token.tokenValue = string(c)
break
case '}':
token.tokenType = END_OBJ
token.tokenValue = string(c)
break
case ',':
token.tokenType = COMMA
token.tokenValue = string(c)
break
case ':':
token.tokenType = COLON
token.tokenValue = string(c)
break
case '"':
token.tokenType = STRING
token.tokenValue = ""
for i++; str[i] != '"'; i++ {
token.tokenValue = token.tokenValue + string(str[i])
}
break
default:
if c == '-' || (str[i] <= '9' && str[i] >= '0') {
token.tokenType = NUMBER
token.tokenValue = string(c)
for i++; str[i] <= '9' && str[i] >= '0'; i++ {
token.tokenValue = token.tokenValue + string(str[i])
}
i--
break
}
err = errors.New("INVALID JSON")
return
}
tokenList = append(tokenList, token)
}
return
}