Best Go-testdeep code snippet using json.Parse
gjson.go
Source:gjson.go
...158 return 0159 case True:160 return 1161 case String:162 n, _ := strconv.ParseFloat(t.Str, 64)163 return n164 case Number:165 return t.Num166 }167}168// Time returns a time.Time representation.169func (t Result) Time() time.Time {170 res, _ := time.Parse(time.RFC3339, t.String())171 return res172}173// Array returns back an array of values.174// If the result represents a non-existent value, then an empty array will be175// returned. If the result is not a JSON array, the return value will be an176// array containing one result.177func (t Result) Array() []Result {178 if t.Type == Null {179 return []Result{}180 }181 if t.Type != JSON {182 return []Result{t}183 }184 r := t.arrayOrMap('[', false)185 return r.a186}187// IsObject returns true if the result value is a JSON object.188func (t Result) IsObject() bool {189 return t.Type == JSON && len(t.Raw) > 0 && t.Raw[0] == '{'190}191// IsArray returns true if the result value is a JSON array.192func (t Result) IsArray() bool {193 return t.Type == JSON && len(t.Raw) > 0 && t.Raw[0] == '['194}195// ForEach iterates through values.196// If the result represents a non-existent value, then no values will be197// iterated. If the result is an Object, the iterator will pass the key and198// value of each item. If the result is an Array, the iterator will only pass199// the value of each item. If the result is not a JSON array or object, the200// iterator will pass back one value equal to the result.201func (t Result) ForEach(iterator func(key, value Result) bool) {202 if !t.Exists() {203 return204 }205 if t.Type != JSON {206 iterator(Result{}, t)207 return208 }209 json := t.Raw210 var keys bool211 var i int212 var key, value Result213 for ; i < len(json); i++ {214 if json[i] == '{' {215 i++216 key.Type = String217 keys = true218 break219 } else if json[i] == '[' {220 i++221 break222 }223 if json[i] > ' ' {224 return225 }226 }227 var str string228 var vesc bool229 var ok bool230 for ; i < len(json); i++ {231 if keys {232 if json[i] != '"' {233 continue234 }235 s := i236 i, str, vesc, ok = parseString(json, i+1)237 if !ok {238 return239 }240 if vesc {241 key.Str = unescape(str[1 : len(str)-1])242 } else {243 key.Str = str[1 : len(str)-1]244 }245 key.Raw = str246 key.Index = s247 }248 for ; i < len(json); i++ {249 if json[i] <= ' ' || json[i] == ',' || json[i] == ':' {250 continue251 }252 break253 }254 s := i255 i, value, ok = parseAny(json, i, true)256 if !ok {257 return258 }259 value.Index = s260 if !iterator(key, value) {261 return262 }263 }264}265// Map returns back an map of values. The result should be a JSON array.266func (t Result) Map() map[string]Result {267 if t.Type != JSON {268 return map[string]Result{}269 }270 r := t.arrayOrMap('{', false)271 return r.o272}273// Get searches result for the specified path.274// The result should be a JSON array or object.275func (t Result) Get(path string) Result {276 return Get(t.Raw, path)277}278type arrayOrMapResult struct {279 a []Result280 ai []interface{}281 o map[string]Result282 oi map[string]interface{}283 vc byte284}285func (t Result) arrayOrMap(vc byte, valueize bool) (r arrayOrMapResult) {286 var json = t.Raw287 var i int288 var value Result289 var count int290 var key Result291 if vc == 0 {292 for ; i < len(json); i++ {293 if json[i] == '{' || json[i] == '[' {294 r.vc = json[i]295 i++296 break297 }298 if json[i] > ' ' {299 goto end300 }301 }302 } else {303 for ; i < len(json); i++ {304 if json[i] == vc {305 i++306 break307 }308 if json[i] > ' ' {309 goto end310 }311 }312 r.vc = vc313 }314 if r.vc == '{' {315 if valueize {316 r.oi = make(map[string]interface{})317 } else {318 r.o = make(map[string]Result)319 }320 } else {321 if valueize {322 r.ai = make([]interface{}, 0)323 } else {324 r.a = make([]Result, 0)325 }326 }327 for ; i < len(json); i++ {328 if json[i] <= ' ' {329 continue330 }331 // get next value332 if json[i] == ']' || json[i] == '}' {333 break334 }335 switch json[i] {336 default:337 if (json[i] >= '0' && json[i] <= '9') || json[i] == '-' {338 value.Type = Number339 value.Raw, value.Num = tonum(json[i:])340 value.Str = ""341 } else {342 continue343 }344 case '{', '[':345 value.Type = JSON346 value.Raw = squash(json[i:])347 value.Str, value.Num = "", 0348 case 'n':349 value.Type = Null350 value.Raw = tolit(json[i:])351 value.Str, value.Num = "", 0352 case 't':353 value.Type = True354 value.Raw = tolit(json[i:])355 value.Str, value.Num = "", 0356 case 'f':357 value.Type = False358 value.Raw = tolit(json[i:])359 value.Str, value.Num = "", 0360 case '"':361 value.Type = String362 value.Raw, value.Str = tostr(json[i:])363 value.Num = 0364 }365 i += len(value.Raw) - 1366 if r.vc == '{' {367 if count%2 == 0 {368 key = value369 } else {370 if valueize {371 if _, ok := r.oi[key.Str]; !ok {372 r.oi[key.Str] = value.Value()373 }374 } else {375 if _, ok := r.o[key.Str]; !ok {376 r.o[key.Str] = value377 }378 }379 }380 count++381 } else {382 if valueize {383 r.ai = append(r.ai, value.Value())384 } else {385 r.a = append(r.a, value)386 }387 }388 }389end:390 return391}392// Parse parses the json and returns a result.393//394// This function expects that the json is well-formed, and does not validate.395// Invalid json will not panic, but it may return back unexpected results.396// If you are consuming JSON from an unpredictable source then you may want to397// use the Valid function first.398func Parse(json string) Result {399 var value Result400 for i := 0; i < len(json); i++ {401 if json[i] == '{' || json[i] == '[' {402 value.Type = JSON403 value.Raw = json[i:] // just take the entire raw404 break405 }406 if json[i] <= ' ' {407 continue408 }409 switch json[i] {410 default:411 if (json[i] >= '0' && json[i] <= '9') || json[i] == '-' {412 value.Type = Number413 value.Raw, value.Num = tonum(json[i:])414 } else {415 return Result{}416 }417 case 'n':418 value.Type = Null419 value.Raw = tolit(json[i:])420 case 't':421 value.Type = True422 value.Raw = tolit(json[i:])423 case 'f':424 value.Type = False425 value.Raw = tolit(json[i:])426 case '"':427 value.Type = String428 value.Raw, value.Str = tostr(json[i:])429 }430 break431 }432 return value433}434// ParseBytes parses the json and returns a result.435// If working with bytes, this method preferred over Parse(string(data))436func ParseBytes(json []byte) Result {437 return Parse(string(json))438}439func squash(json string) string {440 // expects that the lead character is a '[' or '{' or '(' or '"'441 // squash the value, ignoring all nested arrays and objects.442 var i, depth int443 if json[0] != '"' {444 i, depth = 1, 1445 }446 for ; i < len(json); i++ {447 if json[i] >= '"' && json[i] <= '}' {448 switch json[i] {449 case '"':450 i++451 s2 := i452 for ; i < len(json); i++ {453 if json[i] > '\\' {454 continue455 }456 if json[i] == '"' {457 // look for an escaped slash458 if json[i-1] == '\\' {459 n := 0460 for j := i - 2; j > s2-1; j-- {461 if json[j] != '\\' {462 break463 }464 n++465 }466 if n%2 == 0 {467 continue468 }469 }470 break471 }472 }473 if depth == 0 {474 return json[:i+1]475 }476 case '{', '[', '(':477 depth++478 case '}', ']', ')':479 depth--480 if depth == 0 {481 return json[:i+1]482 }483 }484 }485 }486 return json487}488func tonum(json string) (raw string, num float64) {489 for i := 1; i < len(json); i++ {490 // less than dash might have valid characters491 if json[i] <= '-' {492 if json[i] <= ' ' || json[i] == ',' {493 // break on whitespace and comma494 raw = json[:i]495 num, _ = strconv.ParseFloat(raw, 64)496 return497 }498 // could be a '+' or '-'. let's assume so.499 continue500 }501 if json[i] < ']' {502 // probably a valid number503 continue504 }505 if json[i] == 'e' || json[i] == 'E' {506 // allow for exponential numbers507 continue508 }509 // likely a ']' or '}'510 raw = json[:i]511 num, _ = strconv.ParseFloat(raw, 64)512 return513 }514 raw = json515 num, _ = strconv.ParseFloat(raw, 64)516 return517}518func tolit(json string) (raw string) {519 for i := 1; i < len(json); i++ {520 if json[i] < 'a' || json[i] > 'z' {521 return json[:i]522 }523 }524 return json525}526func tostr(json string) (raw string, str string) {527 // expects that the lead character is a '"'528 for i := 1; i < len(json); i++ {529 if json[i] > '\\' {530 continue531 }532 if json[i] == '"' {533 return json[:i+1], json[1:i]534 }535 if json[i] == '\\' {536 i++537 for ; i < len(json); i++ {538 if json[i] > '\\' {539 continue540 }541 if json[i] == '"' {542 // look for an escaped slash543 if json[i-1] == '\\' {544 n := 0545 for j := i - 2; j > 0; j-- {546 if json[j] != '\\' {547 break548 }549 n++550 }551 if n%2 == 0 {552 continue553 }554 }555 break556 }557 }558 var ret string559 if i+1 < len(json) {560 ret = json[:i+1]561 } else {562 ret = json[:i]563 }564 return ret, unescape(json[1:i])565 }566 }567 return json, json[1:]568}569// Exists returns true if value exists.570//571// if gjson.Get(json, "name.last").Exists(){572// println("value exists")573// }574func (t Result) Exists() bool {575 return t.Type != Null || len(t.Raw) != 0576}577// Value returns one of these types:578//579// bool, for JSON booleans580// float64, for JSON numbers581// Number, for JSON numbers582// string, for JSON string literals583// nil, for JSON null584// map[string]interface{}, for JSON objects585// []interface{}, for JSON arrays586//587func (t Result) Value() interface{} {588 if t.Type == String {589 return t.Str590 }591 switch t.Type {592 default:593 return nil594 case False:595 return false596 case Number:597 return t.Num598 case JSON:599 r := t.arrayOrMap(0, true)600 if r.vc == '{' {601 return r.oi602 } else if r.vc == '[' {603 return r.ai604 }605 return nil606 case True:607 return true608 }609}610func parseString(json string, i int) (int, string, bool, bool) {611 var s = i612 for ; i < len(json); i++ {613 if json[i] > '\\' {614 continue615 }616 if json[i] == '"' {617 return i + 1, json[s-1 : i+1], false, true618 }619 if json[i] == '\\' {620 i++621 for ; i < len(json); i++ {622 if json[i] > '\\' {623 continue624 }625 if json[i] == '"' {626 // look for an escaped slash627 if json[i-1] == '\\' {628 n := 0629 for j := i - 2; j > 0; j-- {630 if json[j] != '\\' {631 break632 }633 n++634 }635 if n%2 == 0 {636 continue637 }638 }639 return i + 1, json[s-1 : i+1], true, true640 }641 }642 break643 }644 }645 return i, json[s-1:], false, false646}647func parseNumber(json string, i int) (int, string) {648 var s = i649 i++650 for ; i < len(json); i++ {651 if json[i] <= ' ' || json[i] == ',' || json[i] == ']' ||652 json[i] == '}' {653 return i, json[s:i]654 }655 }656 return i, json[s:]657}658func parseLiteral(json string, i int) (int, string) {659 var s = i660 i++661 for ; i < len(json); i++ {662 if json[i] < 'a' || json[i] > 'z' {663 return i, json[s:i]664 }665 }666 return i, json[s:]667}668type arrayPathResult struct {669 part string670 path string671 pipe string672 piped bool673 more bool674 alogok bool675 arrch bool676 alogkey string677 query struct {678 on bool679 path string680 op string681 value string682 all bool683 }684}685func parseArrayPath(path string) (r arrayPathResult) {686 for i := 0; i < len(path); i++ {687 if path[i] == '|' {688 r.part = path[:i]689 r.pipe = path[i+1:]690 r.piped = true691 return692 }693 if path[i] == '.' {694 r.part = path[:i]695 r.path = path[i+1:]696 r.more = true697 return698 }699 if path[i] == '#' {700 r.arrch = true701 if i == 0 && len(path) > 1 {702 if path[1] == '.' {703 r.alogok = true704 r.alogkey = path[2:]705 r.path = path[:1]706 } else if path[1] == '[' || path[1] == '(' {707 // query708 r.query.on = true709 if true {710 qpath, op, value, _, fi, ok := parseQuery(path[i:])711 if !ok {712 // bad query, end now713 break714 }715 r.query.path = qpath716 r.query.op = op717 r.query.value = value718 i = fi - 1719 if i+1 < len(path) && path[i+1] == '#' {720 r.query.all = true721 }722 } else {723 var end byte724 if path[1] == '[' {725 end = ']'726 } else {727 end = ')'728 }729 i += 2730 // whitespace731 for ; i < len(path); i++ {732 if path[i] > ' ' {733 break734 }735 }736 s := i737 for ; i < len(path); i++ {738 if path[i] <= ' ' ||739 path[i] == '!' ||740 path[i] == '=' ||741 path[i] == '<' ||742 path[i] == '>' ||743 path[i] == '%' ||744 path[i] == end {745 break746 }747 }748 r.query.path = path[s:i]749 // whitespace750 for ; i < len(path); i++ {751 if path[i] > ' ' {752 break753 }754 }755 if i < len(path) {756 s = i757 if path[i] == '!' {758 if i < len(path)-1 && (path[i+1] == '=' ||759 path[i+1] == '%') {760 i++761 }762 } else if path[i] == '<' || path[i] == '>' {763 if i < len(path)-1 && path[i+1] == '=' {764 i++765 }766 } else if path[i] == '=' {767 if i < len(path)-1 && path[i+1] == '=' {768 s++769 i++770 }771 }772 i++773 r.query.op = path[s:i]774 // whitespace775 for ; i < len(path); i++ {776 if path[i] > ' ' {777 break778 }779 }780 s = i781 for ; i < len(path); i++ {782 if path[i] == '"' {783 i++784 s2 := i785 for ; i < len(path); i++ {786 if path[i] > '\\' {787 continue788 }789 if path[i] == '"' {790 // look for an escaped slash791 if path[i-1] == '\\' {792 n := 0793 for j := i - 2; j > s2-1; j-- {794 if path[j] != '\\' {795 break796 }797 n++798 }799 if n%2 == 0 {800 continue801 }802 }803 break804 }805 }806 } else if path[i] == end {807 if i+1 < len(path) && path[i+1] == '#' {808 r.query.all = true809 }810 break811 }812 }813 if i > len(path) {814 i = len(path)815 }816 v := path[s:i]817 for len(v) > 0 && v[len(v)-1] <= ' ' {818 v = v[:len(v)-1]819 }820 r.query.value = v821 }822 }823 }824 }825 continue826 }827 }828 r.part = path829 r.path = ""830 return831}832// splitQuery takes a query and splits it into three parts:833// path, op, middle, and right.834// So for this query:835// #(first_name=="Murphy").last836// Becomes837// first_name # path838// =="Murphy" # middle839// .last # right840// Or,841// #(service_roles.#(=="one")).cap842// Becomes843// service_roles.#(=="one") # path844// # middle845// .cap # right846func parseQuery(query string) (847 path, op, value, remain string, i int, ok bool,848) {849 if len(query) < 2 || query[0] != '#' ||850 (query[1] != '(' && query[1] != '[') {851 return "", "", "", "", i, false852 }853 i = 2854 j := 0 // start of value part855 depth := 1856 for ; i < len(query); i++ {857 if depth == 1 && j == 0 {858 switch query[i] {859 case '!', '=', '<', '>', '%':860 // start of the value part861 j = i862 continue863 }864 }865 if query[i] == '\\' {866 i++867 } else if query[i] == '[' || query[i] == '(' {868 depth++869 } else if query[i] == ']' || query[i] == ')' {870 depth--871 if depth == 0 {872 break873 }874 } else if query[i] == '"' {875 // inside selector string, balance quotes876 i++877 for ; i < len(query); i++ {878 if query[i] == '\\' {879 i++880 } else if query[i] == '"' {881 break882 }883 }884 }885 }886 if depth > 0 {887 return "", "", "", "", i, false888 }889 if j > 0 {890 path = trim(query[2:j])891 value = trim(query[j:i])892 remain = query[i+1:]893 // parse the compare op from the value894 var opsz int895 switch {896 case len(value) == 1:897 opsz = 1898 case value[0] == '!' && value[1] == '=':899 opsz = 2900 case value[0] == '!' && value[1] == '%':901 opsz = 2902 case value[0] == '<' && value[1] == '=':903 opsz = 2904 case value[0] == '>' && value[1] == '=':905 opsz = 2906 case value[0] == '=' && value[1] == '=':907 value = value[1:]908 opsz = 1909 case value[0] == '<':910 opsz = 1911 case value[0] == '>':912 opsz = 1913 case value[0] == '=':914 opsz = 1915 case value[0] == '%':916 opsz = 1917 }918 op = value[:opsz]919 value = trim(value[opsz:])920 } else {921 path = trim(query[2:i])922 remain = query[i+1:]923 }924 return path, op, value, remain, i + 1, true925}926func trim(s string) string {927left:928 if len(s) > 0 && s[0] <= ' ' {929 s = s[1:]930 goto left931 }932right:933 if len(s) > 0 && s[len(s)-1] <= ' ' {934 s = s[:len(s)-1]935 goto right936 }937 return s938}939type objectPathResult struct {940 part string941 path string942 pipe string943 piped bool944 wild bool945 more bool946}947func parseObjectPath(path string) (r objectPathResult) {948 for i := 0; i < len(path); i++ {949 if path[i] == '|' {950 r.part = path[:i]951 r.pipe = path[i+1:]952 r.piped = true953 return954 }955 if path[i] == '.' {956 // peek at the next byte and see if it's a '@', '[', or '{'.957 r.part = path[:i]958 if !DisableModifiers &&959 i < len(path)-1 &&960 (path[i+1] == '@' ||961 path[i+1] == '[' || path[i+1] == '{') {962 r.pipe = path[i+1:]963 r.piped = true964 } else {965 r.path = path[i+1:]966 r.more = true967 }968 return969 }970 if path[i] == '*' || path[i] == '?' {971 r.wild = true972 continue973 }974 if path[i] == '\\' {975 // go into escape mode. this is a slower path that976 // strips off the escape character from the part.977 epart := []byte(path[:i])978 i++979 if i < len(path) {980 epart = append(epart, path[i])981 i++982 for ; i < len(path); i++ {983 if path[i] == '\\' {984 i++985 if i < len(path) {986 epart = append(epart, path[i])987 }988 continue989 } else if path[i] == '.' {990 r.part = string(epart)991 // peek at the next byte and see if it's a '@' modifier992 if !DisableModifiers &&993 i < len(path)-1 && path[i+1] == '@' {994 r.pipe = path[i+1:]995 r.piped = true996 } else {997 r.path = path[i+1:]998 r.more = true999 }1000 r.more = true1001 return1002 } else if path[i] == '|' {1003 r.part = string(epart)1004 r.pipe = path[i+1:]1005 r.piped = true1006 return1007 } else if path[i] == '*' || path[i] == '?' {1008 r.wild = true1009 }1010 epart = append(epart, path[i])1011 }1012 }1013 // append the last part1014 r.part = string(epart)1015 return1016 }1017 }1018 r.part = path1019 return1020}1021func parseSquash(json string, i int) (int, string) {1022 // expects that the lead character is a '[' or '{' or '('1023 // squash the value, ignoring all nested arrays and objects.1024 // the first '[' or '{' or '(' has already been read1025 s := i1026 i++1027 depth := 11028 for ; i < len(json); i++ {1029 if json[i] >= '"' && json[i] <= '}' {1030 switch json[i] {1031 case '"':1032 i++1033 s2 := i1034 for ; i < len(json); i++ {1035 if json[i] > '\\' {1036 continue1037 }1038 if json[i] == '"' {1039 // look for an escaped slash1040 if json[i-1] == '\\' {1041 n := 01042 for j := i - 2; j > s2-1; j-- {1043 if json[j] != '\\' {1044 break1045 }1046 n++1047 }1048 if n%2 == 0 {1049 continue1050 }1051 }1052 break1053 }1054 }1055 case '{', '[', '(':1056 depth++1057 case '}', ']', ')':1058 depth--1059 if depth == 0 {1060 i++1061 return i, json[s:i]1062 }1063 }1064 }1065 }1066 return i, json[s:]1067}1068func parseObject(c *parseContext, i int, path string) (int, bool) {1069 var pmatch, kesc, vesc, ok, hit bool1070 var key, val string1071 rp := parseObjectPath(path)1072 if !rp.more && rp.piped {1073 c.pipe = rp.pipe1074 c.piped = true1075 }1076 for i < len(c.json) {1077 for ; i < len(c.json); i++ {1078 if c.json[i] == '"' {1079 // parse_key_string1080 // this is slightly different from getting s string value1081 // because we don't need the outer quotes.1082 i++1083 var s = i1084 for ; i < len(c.json); i++ {1085 if c.json[i] > '\\' {1086 continue1087 }1088 if c.json[i] == '"' {1089 i, key, kesc, ok = i+1, c.json[s:i], false, true1090 goto parse_key_string_done1091 }1092 if c.json[i] == '\\' {1093 i++1094 for ; i < len(c.json); i++ {1095 if c.json[i] > '\\' {1096 continue1097 }1098 if c.json[i] == '"' {1099 // look for an escaped slash1100 if c.json[i-1] == '\\' {1101 n := 01102 for j := i - 2; j > 0; j-- {1103 if c.json[j] != '\\' {1104 break1105 }1106 n++1107 }1108 if n%2 == 0 {1109 continue1110 }1111 }1112 i, key, kesc, ok = i+1, c.json[s:i], true, true1113 goto parse_key_string_done1114 }1115 }1116 break1117 }1118 }1119 key, kesc, ok = c.json[s:], false, false1120 parse_key_string_done:1121 break1122 }1123 if c.json[i] == '}' {1124 return i + 1, false1125 }1126 }1127 if !ok {1128 return i, false1129 }1130 if rp.wild {1131 if kesc {1132 pmatch = match.Match(unescape(key), rp.part)1133 } else {1134 pmatch = match.Match(key, rp.part)1135 }1136 } else {1137 if kesc {1138 pmatch = rp.part == unescape(key)1139 } else {1140 pmatch = rp.part == key1141 }1142 }1143 hit = pmatch && !rp.more1144 for ; i < len(c.json); i++ {1145 switch c.json[i] {1146 default:1147 continue1148 case '"':1149 i++1150 i, val, vesc, ok = parseString(c.json, i)1151 if !ok {1152 return i, false1153 }1154 if hit {1155 if vesc {1156 c.value.Str = unescape(val[1 : len(val)-1])1157 } else {1158 c.value.Str = val[1 : len(val)-1]1159 }1160 c.value.Raw = val1161 c.value.Type = String1162 return i, true1163 }1164 case '{':1165 if pmatch && !hit {1166 i, hit = parseObject(c, i+1, rp.path)1167 if hit {1168 return i, true1169 }1170 } else {1171 i, val = parseSquash(c.json, i)1172 if hit {1173 c.value.Raw = val1174 c.value.Type = JSON1175 return i, true1176 }1177 }1178 case '[':1179 if pmatch && !hit {1180 i, hit = parseArray(c, i+1, rp.path)1181 if hit {1182 return i, true1183 }1184 } else {1185 i, val = parseSquash(c.json, i)1186 if hit {1187 c.value.Raw = val1188 c.value.Type = JSON1189 return i, true1190 }1191 }1192 case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':1193 i, val = parseNumber(c.json, i)1194 if hit {1195 c.value.Raw = val1196 c.value.Type = Number1197 c.value.Num, _ = strconv.ParseFloat(val, 64)1198 return i, true1199 }1200 case 't', 'f', 'n':1201 vc := c.json[i]1202 i, val = parseLiteral(c.json, i)1203 if hit {1204 c.value.Raw = val1205 switch vc {1206 case 't':1207 c.value.Type = True1208 case 'f':1209 c.value.Type = False1210 }1211 return i, true1212 }1213 }1214 break1215 }1216 }1217 return i, false1218}1219func queryMatches(rp *arrayPathResult, value Result) bool {1220 rpv := rp.query.value1221 if len(rpv) > 2 && rpv[0] == '"' && rpv[len(rpv)-1] == '"' {1222 rpv = rpv[1 : len(rpv)-1]1223 }1224 if !value.Exists() {1225 return false1226 }1227 if rp.query.op == "" {1228 // the query is only looking for existence, such as:1229 // friends.#(name)1230 // which makes sure that the array "friends" has an element of1231 // "name" that exists1232 return true1233 }1234 switch value.Type {1235 case String:1236 switch rp.query.op {1237 case "=":1238 return value.Str == rpv1239 case "!=":1240 return value.Str != rpv1241 case "<":1242 return value.Str < rpv1243 case "<=":1244 return value.Str <= rpv1245 case ">":1246 return value.Str > rpv1247 case ">=":1248 return value.Str >= rpv1249 case "%":1250 return match.Match(value.Str, rpv)1251 case "!%":1252 return !match.Match(value.Str, rpv)1253 }1254 case Number:1255 rpvn, _ := strconv.ParseFloat(rpv, 64)1256 switch rp.query.op {1257 case "=":1258 return value.Num == rpvn1259 case "!=":1260 return value.Num != rpvn1261 case "<":1262 return value.Num < rpvn1263 case "<=":1264 return value.Num <= rpvn1265 case ">":1266 return value.Num > rpvn1267 case ">=":1268 return value.Num >= rpvn1269 }1270 case True:1271 switch rp.query.op {1272 case "=":1273 return rpv == "true"1274 case "!=":1275 return rpv != "true"1276 case ">":1277 return rpv == "false"1278 case ">=":1279 return true1280 }1281 case False:1282 switch rp.query.op {1283 case "=":1284 return rpv == "false"1285 case "!=":1286 return rpv != "false"1287 case "<":1288 return rpv == "true"1289 case "<=":1290 return true1291 }1292 }1293 return false1294}1295func parseArray(c *parseContext, i int, path string) (int, bool) {1296 var pmatch, vesc, ok, hit bool1297 var val string1298 var h int1299 var alog []int1300 var partidx int1301 var multires []byte1302 rp := parseArrayPath(path)1303 if !rp.arrch {1304 n, ok := parseUint(rp.part)1305 if !ok {1306 partidx = -11307 } else {1308 partidx = int(n)1309 }1310 }1311 if !rp.more && rp.piped {1312 c.pipe = rp.pipe1313 c.piped = true1314 }1315 procQuery := func(qval Result) bool {1316 if rp.query.all {1317 if len(multires) == 0 {1318 multires = append(multires, '[')1319 }1320 }1321 var res Result1322 if qval.Type == JSON {1323 res = qval.Get(rp.query.path)1324 } else {1325 if rp.query.path != "" {1326 return false1327 }1328 res = qval1329 }1330 if queryMatches(&rp, res) {1331 if rp.more {1332 left, right, ok := splitPossiblePipe(rp.path)1333 if ok {1334 rp.path = left1335 c.pipe = right1336 c.piped = true1337 }1338 res = qval.Get(rp.path)1339 } else {1340 res = qval1341 }1342 if rp.query.all {1343 raw := res.Raw1344 if len(raw) == 0 {1345 raw = res.String()1346 }1347 if raw != "" {1348 if len(multires) > 1 {1349 multires = append(multires, ',')1350 }1351 multires = append(multires, raw...)1352 }1353 } else {1354 c.value = res1355 return true1356 }1357 }1358 return false1359 }1360 for i < len(c.json)+1 {1361 if !rp.arrch {1362 pmatch = partidx == h1363 hit = pmatch && !rp.more1364 }1365 h++1366 if rp.alogok {1367 alog = append(alog, i)1368 }1369 for ; ; i++ {1370 var ch byte1371 if i > len(c.json) {1372 break1373 } else if i == len(c.json) {1374 ch = ']'1375 } else {1376 ch = c.json[i]1377 }1378 switch ch {1379 default:1380 continue1381 case '"':1382 i++1383 i, val, vesc, ok = parseString(c.json, i)1384 if !ok {1385 return i, false1386 }1387 if rp.query.on {1388 var qval Result1389 if vesc {1390 qval.Str = unescape(val[1 : len(val)-1])1391 } else {1392 qval.Str = val[1 : len(val)-1]1393 }1394 qval.Raw = val1395 qval.Type = String1396 if procQuery(qval) {1397 return i, true1398 }1399 } else if hit {1400 if rp.alogok {1401 break1402 }1403 if vesc {1404 c.value.Str = unescape(val[1 : len(val)-1])1405 } else {1406 c.value.Str = val[1 : len(val)-1]1407 }1408 c.value.Raw = val1409 c.value.Type = String1410 return i, true1411 }1412 case '{':1413 if pmatch && !hit {1414 i, hit = parseObject(c, i+1, rp.path)1415 if hit {1416 if rp.alogok {1417 break1418 }1419 return i, true1420 }1421 } else {1422 i, val = parseSquash(c.json, i)1423 if rp.query.on {1424 if procQuery(Result{Raw: val, Type: JSON}) {1425 return i, true1426 }1427 } else if hit {1428 if rp.alogok {1429 break1430 }1431 c.value.Raw = val1432 c.value.Type = JSON1433 return i, true1434 }1435 }1436 case '[':1437 if pmatch && !hit {1438 i, hit = parseArray(c, i+1, rp.path)1439 if hit {1440 if rp.alogok {1441 break1442 }1443 return i, true1444 }1445 } else {1446 i, val = parseSquash(c.json, i)1447 if rp.query.on {1448 if procQuery(Result{Raw: val, Type: JSON}) {1449 return i, true1450 }1451 } else if hit {1452 if rp.alogok {1453 break1454 }1455 c.value.Raw = val1456 c.value.Type = JSON1457 return i, true1458 }1459 }1460 case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':1461 i, val = parseNumber(c.json, i)1462 if rp.query.on {1463 var qval Result1464 qval.Raw = val1465 qval.Type = Number1466 qval.Num, _ = strconv.ParseFloat(val, 64)1467 if procQuery(qval) {1468 return i, true1469 }1470 } else if hit {1471 if rp.alogok {1472 break1473 }1474 c.value.Raw = val1475 c.value.Type = Number1476 c.value.Num, _ = strconv.ParseFloat(val, 64)1477 return i, true1478 }1479 case 't', 'f', 'n':1480 vc := c.json[i]1481 i, val = parseLiteral(c.json, i)1482 if rp.query.on {1483 var qval Result1484 qval.Raw = val1485 switch vc {1486 case 't':1487 qval.Type = True1488 case 'f':1489 qval.Type = False1490 }1491 if procQuery(qval) {1492 return i, true1493 }1494 } else if hit {1495 if rp.alogok {1496 break1497 }1498 c.value.Raw = val1499 switch vc {1500 case 't':1501 c.value.Type = True1502 case 'f':1503 c.value.Type = False1504 }1505 return i, true1506 }1507 case ']':1508 if rp.arrch && rp.part == "#" {1509 if rp.alogok {1510 left, right, ok := splitPossiblePipe(rp.alogkey)1511 if ok {1512 rp.alogkey = left1513 c.pipe = right1514 c.piped = true1515 }1516 var jsons = make([]byte, 0, 64)1517 jsons = append(jsons, '[')1518 for j, k := 0, 0; j < len(alog); j++ {1519 idx := alog[j]1520 for idx < len(c.json) {1521 switch c.json[idx] {1522 case ' ', '\t', '\r', '\n':1523 idx++1524 continue1525 }1526 break1527 }1528 if idx < len(c.json) && c.json[idx] != ']' {1529 _, res, ok := parseAny(c.json, idx, true)1530 if ok {1531 res := res.Get(rp.alogkey)1532 if res.Exists() {1533 if k > 0 {1534 jsons = append(jsons, ',')1535 }1536 raw := res.Raw1537 if len(raw) == 0 {1538 raw = res.String()1539 }1540 jsons = append(jsons, []byte(raw)...)1541 k++1542 }1543 }1544 }1545 }1546 jsons = append(jsons, ']')1547 c.value.Type = JSON1548 c.value.Raw = string(jsons)1549 return i + 1, true1550 }1551 if rp.alogok {1552 break1553 }1554 c.value.Type = Number1555 c.value.Num = float64(h - 1)1556 c.value.Raw = strconv.Itoa(h - 1)1557 c.calcd = true1558 return i + 1, true1559 }1560 if len(multires) > 0 && !c.value.Exists() {1561 c.value = Result{1562 Raw: string(append(multires, ']')),1563 Type: JSON,1564 }1565 }1566 return i + 1, false1567 }1568 break1569 }1570 }1571 return i, false1572}1573func splitPossiblePipe(path string) (left, right string, ok bool) {1574 // take a quick peek for the pipe character. If found we'll split the piped1575 // part of the path into the c.pipe field and shorten the rp.1576 var possible bool1577 for i := 0; i < len(path); i++ {1578 if path[i] == '|' {1579 possible = true1580 break1581 }1582 }1583 if !possible {1584 return1585 }1586 if len(path) > 0 && path[0] == '{' {1587 squashed := squash(path[1:])1588 if len(squashed) < len(path)-1 {1589 squashed = path[:len(squashed)+1]1590 remain := path[len(squashed):]1591 if remain[0] == '|' {1592 return squashed, remain[1:], true1593 }1594 }1595 return1596 }1597 // split the left and right side of the path with the pipe character as1598 // the delimiter. This is a little tricky because we'll need to basically1599 // parse the entire path.1600 for i := 0; i < len(path); i++ {1601 if path[i] == '\\' {1602 i++1603 } else if path[i] == '.' {1604 if i == len(path)-1 {1605 return1606 }1607 if path[i+1] == '#' {1608 i += 21609 if i == len(path) {1610 return1611 }1612 if path[i] == '[' || path[i] == '(' {1613 var start, end byte1614 if path[i] == '[' {1615 start, end = '[', ']'1616 } else {1617 start, end = '(', ')'1618 }1619 // inside selector, balance brackets1620 i++1621 depth := 11622 for ; i < len(path); i++ {1623 if path[i] == '\\' {1624 i++1625 } else if path[i] == start {1626 depth++1627 } else if path[i] == end {1628 depth--1629 if depth == 0 {1630 break1631 }1632 } else if path[i] == '"' {1633 // inside selector string, balance quotes1634 i++1635 for ; i < len(path); i++ {1636 if path[i] == '\\' {1637 i++1638 } else if path[i] == '"' {1639 break1640 }1641 }1642 }1643 }1644 }1645 }1646 } else if path[i] == '|' {1647 return path[:i], path[i+1:], true1648 }1649 }1650 return1651}1652// ForEachLine iterates through lines of JSON as specified by the JSON Lines1653// format (http://jsonlines.org/).1654// Each line is returned as a GJSON Result.1655func ForEachLine(json string, iterator func(line Result) bool) {1656 var res Result1657 var i int1658 for {1659 i, res, _ = parseAny(json, i, true)1660 if !res.Exists() {1661 break1662 }1663 if !iterator(res) {1664 return1665 }1666 }1667}1668type subSelector struct {1669 name string1670 path string1671}1672// parseSubSelectors returns the subselectors belonging to a '[path1,path2]' or1673// '{"field1":path1,"field2":path2}' type subSelection. It's expected that the1674// first character in path is either '[' or '{', and has already been checked1675// prior to calling this function.1676func parseSubSelectors(path string) (sels []subSelector, out string, ok bool) {1677 modifer := 01678 depth := 11679 colon := 01680 start := 11681 i := 11682 pushSel := func() {1683 var sel subSelector1684 if colon == 0 {1685 sel.path = path[start:i]1686 } else {1687 sel.name = path[start:colon]1688 sel.path = path[colon+1 : i]1689 }1690 sels = append(sels, sel)1691 colon = 01692 start = i + 11693 }1694 for ; i < len(path); i++ {1695 switch path[i] {1696 case '\\':1697 i++1698 case '@':1699 if modifer == 0 && i > 0 && (path[i-1] == '.' || path[i-1] == '|') {1700 modifer = i1701 }1702 case ':':1703 if modifer == 0 && colon == 0 && depth == 1 {1704 colon = i1705 }1706 case ',':1707 if depth == 1 {1708 pushSel()1709 }1710 case '"':1711 i++1712 loop:1713 for ; i < len(path); i++ {1714 switch path[i] {1715 case '\\':1716 i++1717 case '"':1718 break loop1719 }1720 }1721 case '[', '(', '{':1722 depth++1723 case ']', ')', '}':1724 depth--1725 if depth == 0 {1726 pushSel()1727 path = path[i+1:]1728 return sels, path, true1729 }1730 }1731 }1732 return1733}1734// nameOfLast returns the name of the last component1735func nameOfLast(path string) string {1736 for i := len(path) - 1; i >= 0; i-- {1737 if path[i] == '|' || path[i] == '.' {1738 if i > 0 {1739 if path[i-1] == '\\' {1740 continue1741 }1742 }1743 return path[i+1:]1744 }1745 }1746 return path1747}1748func isSimpleName(component string) bool {1749 for i := 0; i < len(component); i++ {1750 if component[i] < ' ' {1751 return false1752 }1753 switch component[i] {1754 case '[', ']', '{', '}', '(', ')', '#', '|':1755 return false1756 }1757 }1758 return true1759}1760func appendJSONString(dst []byte, s string) []byte {1761 for i := 0; i < len(s); i++ {1762 if s[i] < ' ' || s[i] == '\\' || s[i] == '"' || s[i] > 126 {1763 d, _ := json.Marshal(s)1764 return append(dst, string(d)...)1765 }1766 }1767 dst = append(dst, '"')1768 dst = append(dst, s...)1769 dst = append(dst, '"')1770 return dst1771}1772type parseContext struct {1773 json string1774 value Result1775 pipe string1776 piped bool1777 calcd bool1778 lines bool1779}1780// Get searches json for the specified path.1781// A path is in dot syntax, such as "name.last" or "age".1782// When the value is found it's returned immediately.1783//1784// A path is a series of keys searated by a dot.1785// A key may contain special wildcard characters '*' and '?'.1786// To access an array value use the index as the key.1787// To get the number of elements in an array or to access a child path, use1788// the '#' character.1789// The dot and wildcard character can be escaped with '\'.1790//1791// {1792// "name": {"first": "Tom", "last": "Anderson"},1793// "age":37,1794// "children": ["Sara","Alex","Jack"],1795// "friends": [1796// {"first": "James", "last": "Murphy"},1797// {"first": "Roger", "last": "Craig"}1798// ]1799// }1800// "name.last" >> "Anderson"1801// "age" >> 371802// "children" >> ["Sara","Alex","Jack"]1803// "children.#" >> 31804// "children.1" >> "Alex"1805// "child*.2" >> "Jack"1806// "c?ildren.0" >> "Sara"1807// "friends.#.first" >> ["James","Roger"]1808//1809// This function expects that the json is well-formed, and does not validate.1810// Invalid json will not panic, but it may return back unexpected results.1811// If you are consuming JSON from an unpredictable source then you may want to1812// use the Valid function first.1813func Get(json, path string) Result {1814 if len(path) > 1 {1815 if !DisableModifiers {1816 if path[0] == '@' {1817 // possible modifier1818 var ok bool1819 var npath string1820 var rjson string1821 npath, rjson, ok = execModifier(json, path)1822 if ok {1823 path = npath1824 if len(path) > 0 && (path[0] == '|' || path[0] == '.') {1825 res := Get(rjson, path[1:])1826 res.Index = 01827 return res1828 }1829 return Parse(rjson)1830 }1831 }1832 }1833 if path[0] == '[' || path[0] == '{' {1834 // using a subselector path1835 kind := path[0]1836 var ok bool1837 var subs []subSelector1838 subs, path, ok = parseSubSelectors(path)1839 if ok {1840 if len(path) == 0 || (path[0] == '|' || path[0] == '.') {1841 var b []byte1842 b = append(b, kind)1843 var i int1844 for _, sub := range subs {1845 res := Get(json, sub.path)1846 if res.Exists() {1847 if i > 0 {1848 b = append(b, ',')1849 }1850 if kind == '{' {1851 if len(sub.name) > 0 {1852 if sub.name[0] == '"' && Valid(sub.name) {1853 b = append(b, sub.name...)1854 } else {1855 b = appendJSONString(b, sub.name)1856 }1857 } else {1858 last := nameOfLast(sub.path)1859 if isSimpleName(last) {1860 b = appendJSONString(b, last)1861 } else {1862 b = appendJSONString(b, "_")1863 }1864 }1865 b = append(b, ':')1866 }1867 var raw string1868 if len(res.Raw) == 0 {1869 raw = res.String()1870 if len(raw) == 0 {1871 raw = "null"1872 }1873 } else {1874 raw = res.Raw1875 }1876 b = append(b, raw...)1877 i++1878 }1879 }1880 b = append(b, kind+2)1881 var res Result1882 res.Raw = string(b)1883 res.Type = JSON1884 if len(path) > 0 {1885 res = res.Get(path[1:])1886 }1887 res.Index = 01888 return res1889 }1890 }1891 }1892 }1893 var i int1894 var c = &parseContext{json: json}1895 if len(path) >= 2 && path[0] == '.' && path[1] == '.' {1896 c.lines = true1897 parseArray(c, 0, path[2:])1898 } else {1899 for ; i < len(c.json); i++ {1900 if c.json[i] == '{' {1901 i++1902 parseObject(c, i, path)1903 break1904 }1905 if c.json[i] == '[' {1906 i++1907 parseArray(c, i, path)1908 break1909 }1910 }1911 }1912 if c.piped {1913 res := c.value.Get(c.pipe)1914 res.Index = 01915 return res1916 }1917 fillIndex(json, c)1918 return c.value1919}1920// GetBytes searches json for the specified path.1921// If working with bytes, this method preferred over Get(string(data), path)1922func GetBytes(json []byte, path string) Result {1923 return getBytes(json, path)1924}1925// runeit returns the rune from the the \uXXXX1926func runeit(json string) rune {1927 n, _ := strconv.ParseUint(json[:4], 16, 64)1928 return rune(n)1929}1930// unescape unescapes a string1931func unescape(json string) string {1932 var str = make([]byte, 0, len(json))1933 for i := 0; i < len(json); i++ {1934 switch {1935 default:1936 str = append(str, json[i])1937 case json[i] < ' ':1938 return string(str)1939 case json[i] == '\\':1940 i++1941 if i >= len(json) {1942 return string(str)1943 }1944 switch json[i] {1945 default:1946 return string(str)1947 case '\\':1948 str = append(str, '\\')1949 case '/':1950 str = append(str, '/')1951 case 'b':1952 str = append(str, '\b')1953 case 'f':1954 str = append(str, '\f')1955 case 'n':1956 str = append(str, '\n')1957 case 'r':1958 str = append(str, '\r')1959 case 't':1960 str = append(str, '\t')1961 case '"':1962 str = append(str, '"')1963 case 'u':1964 if i+5 > len(json) {1965 return string(str)1966 }1967 r := runeit(json[i+1:])1968 i += 51969 if utf16.IsSurrogate(r) {1970 // need another code1971 if len(json[i:]) >= 6 && json[i] == '\\' &&1972 json[i+1] == 'u' {1973 // we expect it to be correct so just consume it1974 r = utf16.DecodeRune(r, runeit(json[i+2:]))1975 i += 61976 }1977 }1978 // provide enough space to encode the largest utf8 possible1979 str = append(str, 0, 0, 0, 0, 0, 0, 0, 0)1980 n := utf8.EncodeRune(str[len(str)-8:], r)1981 str = str[:len(str)-8+n]1982 i-- // backtrack index by one1983 }1984 }1985 }1986 return string(str)1987}1988// Less return true if a token is less than another token.1989// The caseSensitive paramater is used when the tokens are Strings.1990// The order when comparing two different type is:1991//1992// Null < False < Number < String < True < JSON1993//1994func (t Result) Less(token Result, caseSensitive bool) bool {1995 if t.Type < token.Type {1996 return true1997 }1998 if t.Type > token.Type {1999 return false2000 }2001 if t.Type == String {2002 if caseSensitive {2003 return t.Str < token.Str2004 }2005 return stringLessInsensitive(t.Str, token.Str)2006 }2007 if t.Type == Number {2008 return t.Num < token.Num2009 }2010 return t.Raw < token.Raw2011}2012func stringLessInsensitive(a, b string) bool {2013 for i := 0; i < len(a) && i < len(b); i++ {2014 if a[i] >= 'A' && a[i] <= 'Z' {2015 if b[i] >= 'A' && b[i] <= 'Z' {2016 // both are uppercase, do nothing2017 if a[i] < b[i] {2018 return true2019 } else if a[i] > b[i] {2020 return false2021 }2022 } else {2023 // a is uppercase, convert a to lowercase2024 if a[i]+32 < b[i] {2025 return true2026 } else if a[i]+32 > b[i] {2027 return false2028 }2029 }2030 } else if b[i] >= 'A' && b[i] <= 'Z' {2031 // b is uppercase, convert b to lowercase2032 if a[i] < b[i]+32 {2033 return true2034 } else if a[i] > b[i]+32 {2035 return false2036 }2037 } else {2038 // neither are uppercase2039 if a[i] < b[i] {2040 return true2041 } else if a[i] > b[i] {2042 return false2043 }2044 }2045 }2046 return len(a) < len(b)2047}2048// parseAny parses the next value from a json string.2049// A Result is returned when the hit param is set.2050// The return values are (i int, res Result, ok bool)2051func parseAny(json string, i int, hit bool) (int, Result, bool) {2052 var res Result2053 var val string2054 for ; i < len(json); i++ {2055 if json[i] == '{' || json[i] == '[' {2056 i, val = parseSquash(json, i)2057 if hit {2058 res.Raw = val2059 res.Type = JSON2060 }2061 return i, res, true2062 }2063 if json[i] <= ' ' {2064 continue2065 }2066 switch json[i] {2067 case '"':2068 i++2069 var vesc bool2070 var ok bool2071 i, val, vesc, ok = parseString(json, i)2072 if !ok {2073 return i, res, false2074 }2075 if hit {2076 res.Type = String2077 res.Raw = val2078 if vesc {2079 res.Str = unescape(val[1 : len(val)-1])2080 } else {2081 res.Str = val[1 : len(val)-1]2082 }2083 }2084 return i, res, true2085 case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':2086 i, val = parseNumber(json, i)2087 if hit {2088 res.Raw = val2089 res.Type = Number2090 res.Num, _ = strconv.ParseFloat(val, 64)2091 }2092 return i, res, true2093 case 't', 'f', 'n':2094 vc := json[i]2095 i, val = parseLiteral(json, i)2096 if hit {2097 res.Raw = val2098 switch vc {2099 case 't':2100 res.Type = True2101 case 'f':2102 res.Type = False2103 }2104 return i, res, true2105 }2106 }2107 }2108 return i, res, false2109}2110var ( // used for testing2111 testWatchForFallback bool2112 testLastWasFallback bool2113)2114// GetMany searches json for the multiple paths.2115// The return value is a Result array where the number of items2116// will be equal to the number of input paths.2117func GetMany(json string, path ...string) []Result {2118 res := make([]Result, len(path))2119 for i, path := range path {2120 res[i] = Get(json, path)2121 }2122 return res2123}2124// GetManyBytes searches json for the multiple paths.2125// The return value is a Result array where the number of items2126// will be equal to the number of input paths.2127func GetManyBytes(json []byte, path ...string) []Result {2128 res := make([]Result, len(path))2129 for i, path := range path {2130 res[i] = GetBytes(json, path)2131 }2132 return res2133}2134func validpayload(data []byte, i int) (outi int, ok bool) {2135 for ; i < len(data); i++ {2136 switch data[i] {2137 default:2138 i, ok = validany(data, i)2139 if !ok {2140 return i, false2141 }2142 for ; i < len(data); i++ {2143 switch data[i] {2144 default:2145 return i, false2146 case ' ', '\t', '\n', '\r':2147 continue2148 }2149 }2150 return i, true2151 case ' ', '\t', '\n', '\r':2152 continue2153 }2154 }2155 return i, false2156}2157func validany(data []byte, i int) (outi int, ok bool) {2158 for ; i < len(data); i++ {2159 switch data[i] {2160 default:2161 return i, false2162 case ' ', '\t', '\n', '\r':2163 continue2164 case '{':2165 return validobject(data, i+1)2166 case '[':2167 return validarray(data, i+1)2168 case '"':2169 return validstring(data, i+1)2170 case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':2171 return validnumber(data, i+1)2172 case 't':2173 return validtrue(data, i+1)2174 case 'f':2175 return validfalse(data, i+1)2176 case 'n':2177 return validnull(data, i+1)2178 }2179 }2180 return i, false2181}2182func validobject(data []byte, i int) (outi int, ok bool) {2183 for ; i < len(data); i++ {2184 switch data[i] {2185 default:2186 return i, false2187 case ' ', '\t', '\n', '\r':2188 continue2189 case '}':2190 return i + 1, true2191 case '"':2192 key:2193 if i, ok = validstring(data, i+1); !ok {2194 return i, false2195 }2196 if i, ok = validcolon(data, i); !ok {2197 return i, false2198 }2199 if i, ok = validany(data, i); !ok {2200 return i, false2201 }2202 if i, ok = validcomma(data, i, '}'); !ok {2203 return i, false2204 }2205 if data[i] == '}' {2206 return i + 1, true2207 }2208 i++2209 for ; i < len(data); i++ {2210 switch data[i] {2211 default:2212 return i, false2213 case ' ', '\t', '\n', '\r':2214 continue2215 case '"':2216 goto key2217 }2218 }2219 return i, false2220 }2221 }2222 return i, false2223}2224func validcolon(data []byte, i int) (outi int, ok bool) {2225 for ; i < len(data); i++ {2226 switch data[i] {2227 default:2228 return i, false2229 case ' ', '\t', '\n', '\r':2230 continue2231 case ':':2232 return i + 1, true2233 }2234 }2235 return i, false2236}2237func validcomma(data []byte, i int, end byte) (outi int, ok bool) {2238 for ; i < len(data); i++ {2239 switch data[i] {2240 default:2241 return i, false2242 case ' ', '\t', '\n', '\r':2243 continue2244 case ',':2245 return i, true2246 case end:2247 return i, true2248 }2249 }2250 return i, false2251}2252func validarray(data []byte, i int) (outi int, ok bool) {2253 for ; i < len(data); i++ {2254 switch data[i] {2255 default:2256 for ; i < len(data); i++ {2257 if i, ok = validany(data, i); !ok {2258 return i, false2259 }2260 if i, ok = validcomma(data, i, ']'); !ok {2261 return i, false2262 }2263 if data[i] == ']' {2264 return i + 1, true2265 }2266 }2267 case ' ', '\t', '\n', '\r':2268 continue2269 case ']':2270 return i + 1, true2271 }2272 }2273 return i, false2274}2275func validstring(data []byte, i int) (outi int, ok bool) {2276 for ; i < len(data); i++ {2277 if data[i] < ' ' {2278 return i, false2279 } else if data[i] == '\\' {2280 i++2281 if i == len(data) {2282 return i, false2283 }2284 switch data[i] {2285 default:2286 return i, false2287 case '"', '\\', '/', 'b', 'f', 'n', 'r', 't':2288 case 'u':2289 for j := 0; j < 4; j++ {2290 i++2291 if i >= len(data) {2292 return i, false2293 }2294 if !((data[i] >= '0' && data[i] <= '9') ||2295 (data[i] >= 'a' && data[i] <= 'f') ||2296 (data[i] >= 'A' && data[i] <= 'F')) {2297 return i, false2298 }2299 }2300 }2301 } else if data[i] == '"' {2302 return i + 1, true2303 }2304 }2305 return i, false2306}2307func validnumber(data []byte, i int) (outi int, ok bool) {2308 i--2309 // sign2310 if data[i] == '-' {2311 i++2312 }2313 // int2314 if i == len(data) {2315 return i, false2316 }2317 if data[i] == '0' {2318 i++2319 } else {2320 for ; i < len(data); i++ {2321 if data[i] >= '0' && data[i] <= '9' {2322 continue2323 }2324 break2325 }2326 }2327 // frac2328 if i == len(data) {2329 return i, true2330 }2331 if data[i] == '.' {2332 i++2333 if i == len(data) {2334 return i, false2335 }2336 if data[i] < '0' || data[i] > '9' {2337 return i, false2338 }2339 i++2340 for ; i < len(data); i++ {2341 if data[i] >= '0' && data[i] <= '9' {2342 continue2343 }2344 break2345 }2346 }2347 // exp2348 if i == len(data) {2349 return i, true2350 }2351 if data[i] == 'e' || data[i] == 'E' {2352 i++2353 if i == len(data) {2354 return i, false2355 }2356 if data[i] == '+' || data[i] == '-' {2357 i++2358 }2359 if i == len(data) {2360 return i, false2361 }2362 if data[i] < '0' || data[i] > '9' {2363 return i, false2364 }2365 i++2366 for ; i < len(data); i++ {2367 if data[i] >= '0' && data[i] <= '9' {2368 continue2369 }2370 break2371 }2372 }2373 return i, true2374}2375func validtrue(data []byte, i int) (outi int, ok bool) {2376 if i+3 <= len(data) && data[i] == 'r' && data[i+1] == 'u' &&2377 data[i+2] == 'e' {2378 return i + 3, true2379 }2380 return i, false2381}2382func validfalse(data []byte, i int) (outi int, ok bool) {2383 if i+4 <= len(data) && data[i] == 'a' && data[i+1] == 'l' &&2384 data[i+2] == 's' && data[i+3] == 'e' {2385 return i + 4, true2386 }2387 return i, false2388}2389func validnull(data []byte, i int) (outi int, ok bool) {2390 if i+3 <= len(data) && data[i] == 'u' && data[i+1] == 'l' &&2391 data[i+2] == 'l' {2392 return i + 3, true2393 }2394 return i, false2395}2396// Valid returns true if the input is valid json.2397//2398// if !gjson.Valid(json) {2399// return errors.New("invalid json")2400// }2401// value := gjson.Get(json, "name.last")2402//2403func Valid(json string) bool {2404 _, ok := validpayload(stringBytes(json), 0)2405 return ok2406}2407// ValidBytes returns true if the input is valid json.2408//2409// if !gjson.Valid(json) {2410// return errors.New("invalid json")2411// }2412// value := gjson.Get(json, "name.last")2413//2414// If working with bytes, this method preferred over ValidBytes(string(data))2415//2416func ValidBytes(json []byte) bool {2417 _, ok := validpayload(json, 0)2418 return ok2419}2420func parseUint(s string) (n uint64, ok bool) {2421 var i int2422 if i == len(s) {2423 return 0, false2424 }2425 for ; i < len(s); i++ {2426 if s[i] >= '0' && s[i] <= '9' {2427 n = n*10 + uint64(s[i]-'0')2428 } else {2429 return 0, false2430 }2431 }2432 return n, true2433}2434func parseInt(s string) (n int64, ok bool) {2435 var i int2436 var sign bool2437 if len(s) > 0 && s[0] == '-' {2438 sign = true2439 i++2440 }2441 if i == len(s) {2442 return 0, false2443 }2444 for ; i < len(s); i++ {2445 if s[i] >= '0' && s[i] <= '9' {2446 n = n*10 + int64(s[i]-'0')2447 } else {2448 return 0, false2449 }2450 }2451 if sign {2452 return n * -1, true2453 }2454 return n, true2455}2456const minUint53 = 02457const maxUint53 = 45035996273704952458const minInt53 = -22517998136852482459const maxInt53 = 22517998136852472460func floatToUint(f float64) (n uint64, ok bool) {2461 n = uint64(f)2462 if float64(n) == f && n >= minUint53 && n <= maxUint53 {2463 return n, true2464 }2465 return 0, false2466}2467func floatToInt(f float64) (n int64, ok bool) {2468 n = int64(f)2469 if float64(n) == f && n >= minInt53 && n <= maxInt53 {2470 return n, true2471 }2472 return 0, false2473}2474// execModifier parses the path to find a matching modifier function.2475// then input expects that the path already starts with a '@'2476func execModifier(json, path string) (pathOut, res string, ok bool) {2477 name := path[1:]2478 var hasArgs bool2479 for i := 1; i < len(path); i++ {2480 if path[i] == ':' {2481 pathOut = path[i+1:]2482 name = path[1:i]2483 hasArgs = len(pathOut) > 02484 break2485 }2486 if path[i] == '|' {2487 pathOut = path[i:]2488 name = path[1:i]2489 break2490 }2491 if path[i] == '.' {2492 pathOut = path[i:]2493 name = path[1:i]2494 break2495 }2496 }2497 if fn, ok := modifiers[name]; ok {2498 var args string2499 if hasArgs {2500 var parsedArgs bool2501 switch pathOut[0] {2502 case '{', '[', '"':2503 res := Parse(pathOut)2504 if res.Exists() {2505 args = squash(pathOut)2506 pathOut = pathOut[len(args):]2507 parsedArgs = true2508 }2509 }2510 if !parsedArgs {2511 idx := strings.IndexByte(pathOut, '|')2512 if idx == -1 {2513 args = pathOut2514 pathOut = ""2515 } else {2516 args = pathOut[:idx]2517 pathOut = pathOut[idx:]2518 }2519 }2520 }2521 return pathOut, fn(json, args), true2522 }2523 return pathOut, res, false2524}2525// unwrap removes the '[]' or '{}' characters around json2526func unwrap(json string) string {2527 json = trim(json)2528 if len(json) >= 2 && json[0] == '[' || json[0] == '{' {2529 json = json[1 : len(json)-1]2530 }2531 return json2532}2533// DisableModifiers will disable the modifier syntax2534var DisableModifiers = false2535var modifiers = map[string]func(json, arg string) string{2536 "pretty": modPretty,2537 "ugly": modUgly,2538 "reverse": modReverse,2539 "this": modThis,2540 "flatten": modFlatten,2541 "join": modJoin,2542 "valid": modValid,2543}2544// AddModifier binds a custom modifier command to the GJSON syntax.2545// This operation is not thread safe and should be executed prior to2546// using all other gjson function.2547func AddModifier(name string, fn func(json, arg string) string) {2548 modifiers[name] = fn2549}2550// ModifierExists returns true when the specified modifier exists.2551func ModifierExists(name string, fn func(json, arg string) string) bool {2552 _, ok := modifiers[name]2553 return ok2554}2555// @pretty modifier makes the json look nice.2556func modPretty(json, arg string) string {2557 if len(arg) > 0 {2558 opts := *pretty.DefaultOptions2559 Parse(arg).ForEach(func(key, value Result) bool {2560 switch key.String() {2561 case "sortKeys":2562 opts.SortKeys = value.Bool()2563 case "indent":2564 opts.Indent = value.String()2565 case "prefix":2566 opts.Prefix = value.String()2567 case "width":2568 opts.Width = int(value.Int())2569 }2570 return true2571 })2572 return bytesString(pretty.PrettyOptions(stringBytes(json), &opts))2573 }2574 return bytesString(pretty.Pretty(stringBytes(json)))2575}2576// @this returns the current element. Can be used to retrieve the root element.2577func modThis(json, arg string) string {2578 return json2579}2580// @ugly modifier removes all whitespace.2581func modUgly(json, arg string) string {2582 return bytesString(pretty.Ugly(stringBytes(json)))2583}2584// @reverse reverses array elements or root object members.2585func modReverse(json, arg string) string {2586 res := Parse(json)2587 if res.IsArray() {2588 var values []Result2589 res.ForEach(func(_, value Result) bool {2590 values = append(values, value)2591 return true2592 })2593 out := make([]byte, 0, len(json))2594 out = append(out, '[')2595 for i, j := len(values)-1, 0; i >= 0; i, j = i-1, j+1 {2596 if j > 0 {2597 out = append(out, ',')2598 }2599 out = append(out, values[i].Raw...)2600 }2601 out = append(out, ']')2602 return bytesString(out)2603 }2604 if res.IsObject() {2605 var keyValues []Result2606 res.ForEach(func(key, value Result) bool {2607 keyValues = append(keyValues, key, value)2608 return true2609 })2610 out := make([]byte, 0, len(json))2611 out = append(out, '{')2612 for i, j := len(keyValues)-2, 0; i >= 0; i, j = i-2, j+1 {2613 if j > 0 {2614 out = append(out, ',')2615 }2616 out = append(out, keyValues[i+0].Raw...)2617 out = append(out, ':')2618 out = append(out, keyValues[i+1].Raw...)2619 }2620 out = append(out, '}')2621 return bytesString(out)2622 }2623 return json2624}2625// @flatten an array with child arrays.2626// [1,[2],[3,4],[5,[6,7]]] -> [1,2,3,4,5,[6,7]]2627// The {"deep":true} arg can be provide for deep flattening.2628// [1,[2],[3,4],[5,[6,7]]] -> [1,2,3,4,5,6,7]2629// The original json is returned when the json is not an array.2630func modFlatten(json, arg string) string {2631 res := Parse(json)2632 if !res.IsArray() {2633 return json2634 }2635 var deep bool2636 if arg != "" {2637 Parse(arg).ForEach(func(key, value Result) bool {2638 if key.String() == "deep" {2639 deep = value.Bool()2640 }2641 return true2642 })2643 }2644 var out []byte2645 out = append(out, '[')2646 var idx int2647 res.ForEach(func(_, value Result) bool {2648 if idx > 0 {2649 out = append(out, ',')2650 }2651 if value.IsArray() {2652 if deep {2653 out = append(out, unwrap(modFlatten(value.Raw, arg))...)2654 } else {2655 out = append(out, unwrap(value.Raw)...)2656 }2657 } else {2658 out = append(out, value.Raw...)2659 }2660 idx++2661 return true2662 })2663 out = append(out, ']')2664 return bytesString(out)2665}2666// @join multiple objects into a single object.2667// [{"first":"Tom"},{"last":"Smith"}] -> {"first","Tom","last":"Smith"}2668// The arg can be "true" to specify that duplicate keys should be preserved.2669// [{"first":"Tom","age":37},{"age":41}] -> {"first","Tom","age":37,"age":41}2670// Without preserved keys:2671// [{"first":"Tom","age":37},{"age":41}] -> {"first","Tom","age":41}2672// The original json is returned when the json is not an object.2673func modJoin(json, arg string) string {2674 res := Parse(json)2675 if !res.IsArray() {2676 return json2677 }2678 var preserve bool2679 if arg != "" {2680 Parse(arg).ForEach(func(key, value Result) bool {2681 if key.String() == "preserve" {2682 preserve = value.Bool()2683 }2684 return true2685 })2686 }2687 var out []byte2688 out = append(out, '{')2689 if preserve {2690 // Preserve duplicate keys.2691 var idx int2692 res.ForEach(func(_, value Result) bool {2693 if !value.IsObject() {2694 return true...
parser.go
Source:parser.go
1package antnet2import (3 "reflect"4)5type IMsgParser interface {6 C2S() interface{}7 S2C() interface{}8 C2SData() []byte9 S2CData() []byte10 C2SString() string11 S2CString() string12}13type MsgParser struct {14 s2c interface{}15 c2s interface{}16 c2sFunc ParseFunc17 s2cFunc ParseFunc18 parser IParser19}20func (r *MsgParser) C2S() interface{} {21 if r.c2s == nil && r.c2sFunc != nil {22 r.c2s = r.c2sFunc()23 }24 return r.c2s25}26func (r *MsgParser) S2C() interface{} {27 if r.s2c == nil && r.s2cFunc != nil {28 r.s2c = r.s2cFunc()29 }30 return r.s2c31}32func (r *MsgParser) C2SData() []byte {33 return r.parser.PackMsg(r.C2S())34}35func (r *MsgParser) S2CData() []byte {36 return r.parser.PackMsg(r.S2C())37}38func (r *MsgParser) C2SString() string {39 return string(r.C2SData())40}41func (r *MsgParser) S2CString() string {42 return string(r.S2CData())43}44type ParserType int45const (46 ParserTypePB ParserType = iota //protobufç±»åï¼ç¨äºå客æ·ç«¯äº¤äº47 ParserTypeJson //jsonç±»åï¼å¯ä»¥ç¨äºå®¢æ·ç«¯æè
æå¡å¨ä¹é´äº¤äº48 ParserTypeCmd //cmdç±»åï¼ç±»ä¼¼telnetæ令ï¼ç¨äºç´æ¥åç¨åºäº¤äº49 ParserTypeRaw //ä¸åä»»ä½è§£æ50)51type ParseErrType int52const (53 ParseErrTypeSendRemind ParseErrType = iota //æ¶æ¯è§£æ失败åéæéæ¶æ¯54 ParseErrTypeContinue //æ¶æ¯è§£æ失败åè·³è¿æ¬æ¡æ¶æ¯55 ParseErrTypeAlways //æ¶æ¯è§£æ失败ä¾ç¶å¤ç56 ParseErrTypeClose //æ¶æ¯è§£æ失败åå
³éè¿æ¥57)58type ParseFunc func() interface{}59type IParser interface {60 GetType() ParserType61 GetErrType() ParseErrType62 ParseC2S(msg *Message) (IMsgParser, error)63 PackMsg(v interface{}) []byte64 GetRemindMsg(err error, t MsgType) *Message65}66type Parser struct {67 Type ParserType68 ErrType ParseErrType69 msgMap map[int]MsgParser70 cmdRoot *cmdParseNode71 jsonMap map[string]*jsonParseNode72 parser IParser73}74func (r *Parser) Get() IParser {75 switch r.Type {76 case ParserTypePB:77 if r.parser == nil {78 r.parser = &pBParser{r}79 }80 case ParserTypeJson:81 if r.parser == nil {82 r.parser = &jsonParser{r}83 }84 case ParserTypeCmd:85 return &cmdParser{factory: r}86 case ParserTypeRaw:87 return nil88 }89 return r.parser90}91func (r *Parser) RegisterFunc(cmd, act uint8, c2sFunc ParseFunc, s2cFunc ParseFunc) {92 if r.msgMap == nil {93 r.msgMap = map[int]MsgParser{}94 }95 r.msgMap[CmdAct(cmd, act)] = MsgParser{c2sFunc: c2sFunc, s2cFunc: s2cFunc}96}97func (r *Parser) Register(cmd, act uint8, c2s interface{}, s2c interface{}) {98 if r.msgMap == nil {99 r.msgMap = map[int]MsgParser{}100 }101 p := MsgParser{}102 if c2s != nil {103 c2sType := reflect.TypeOf(c2s).Elem()104 p.c2sFunc = func() interface{} {105 return reflect.New(c2sType).Interface()106 }107 }108 if s2c != nil {109 s2cType := reflect.TypeOf(s2c).Elem()110 p.s2cFunc = func() interface{} {111 return reflect.New(s2cType).Interface()112 }113 }114 if c2s != nil || s2c != nil {115 r.msgMap[CmdAct(cmd, act)] = p116 }117}118func (r *Parser) RegisterMsgFunc(c2sFunc ParseFunc, s2cFunc ParseFunc) {119 if r.Type == ParserTypeCmd {120 if r.cmdRoot == nil {121 r.cmdRoot = &cmdParseNode{}122 }123 registerCmdParser(r.cmdRoot, c2sFunc, s2cFunc)124 }125 if r.Type == ParserTypeJson {126 if r.jsonMap == nil {127 r.jsonMap = map[string]*jsonParseNode{}128 }129 registerJsonParser(r.jsonMap, c2sFunc, s2cFunc)130 }131}132func (r *Parser) RegisterMsg(c2s interface{}, s2c interface{}) {133 var c2sFunc ParseFunc = nil134 var s2cFunc ParseFunc = nil135 if c2s != nil {136 c2sType := reflect.TypeOf(c2s).Elem()137 c2sFunc = func() interface{} {138 return reflect.New(c2sType).Interface()139 }140 }141 if s2c != nil {142 s2cType := reflect.TypeOf(s2c).Elem()143 s2cFunc = func() interface{} {144 return reflect.New(s2cType).Interface()145 }146 }147 if r.Type == ParserTypeCmd {148 if r.cmdRoot == nil {149 r.cmdRoot = &cmdParseNode{}150 }151 registerCmdParser(r.cmdRoot, c2sFunc, s2cFunc)152 }153 if r.Type == ParserTypeJson {154 if r.jsonMap == nil {155 r.jsonMap = map[string]*jsonParseNode{}156 }157 registerJsonParser(r.jsonMap, c2sFunc, s2cFunc)158 }159}...
parser_json.go
Source:parser_json.go
2import (3 "encoding/json"4 "reflect"5)6type jsonParser struct {7 factory *Parser8}9type jsonParseNode struct {10 c2sFunc ParseFunc11 s2cFunc ParseFunc12}13func (r *jsonParser) ParseC2S(msg *Message) (IMsgParser, error) {14 if msg == nil {15 return nil, ErrJsonUnPack16 }17 if msg.Head == nil {18 m := map[string]json.RawMessage{}19 if json.Unmarshal(msg.Data, &m) == nil {20 for k, v := range m {21 node, ok := r.factory.jsonMap[k]22 if ok {23 c2s := node.c2sFunc()24 if json.Unmarshal(v, c2s) == nil {25 return &MsgParser{c2s: c2s, parser: r, s2cFunc: node.s2cFunc}, nil26 }27 }28 }29 }30 } else {31 p, ok := r.factory.msgMap[msg.Head.CmdAct()]32 if ok {33 if p.C2S() != nil {34 err := JsonUnPack(msg.Data, p.C2S())35 if err != nil {36 return nil, err37 }38 p.parser = r39 return &p, nil40 }41 }42 }43 return nil, ErrJsonUnPack44}45func (r *jsonParser) PackMsg(v interface{}) []byte {46 data, _ := JsonPack(v)47 return data48}49func (r *jsonParser) GetRemindMsg(err error, t MsgType) *Message {50 if t == MsgTypeMsg {51 return NewErrMsg(err)52 } else {53 return NewStrMsg(err.Error() + "\n")54 }55}56func (r *jsonParser) GetType() ParserType {57 return r.factory.Type58}59func (r *jsonParser) GetErrType() ParseErrType {60 return r.factory.ErrType61}62func JsonUnPack(data []byte, msg interface{}) error {63 if data == nil || msg == nil {64 return ErrJsonUnPack65 }66 err := json.Unmarshal(data, msg)67 if err != nil {68 return ErrJsonUnPack69 }70 return nil71}72func JsonPack(msg interface{}) ([]byte, error) {73 if msg == nil {74 return nil, ErrJsonPack75 }76 data, err := json.Marshal(msg)77 if err != nil {78 LogInfo("")79 return nil, ErrJsonPack80 }81 return data, nil82}83func registerJsonParser(jm map[string]*jsonParseNode, c2sFunc ParseFunc, s2cFunc ParseFunc) {84 msgType := reflect.TypeOf(c2sFunc())85 if msgType == nil || msgType.Kind() != reflect.Ptr {86 LogFatal("message pointer required")87 return88 }89 typ := msgType.Elem()90 jm[typ.Name()] = &jsonParseNode{c2sFunc, s2cFunc}91}...
Parse
Using AI Code Generation
1import (2type Response1 struct {3}4type Response2 struct {5}6func main() {7 bolB, _ := json.Marshal(true)8 fmt.Println(string(bolB))9 intB, _ := json.Marshal(1)10 fmt.Println(string(intB))11 fltB, _ := json.Marshal(2.34)12 fmt.Println(string(fltB))13 strB, _ := json.Marshal("gopher")14 fmt.Println(string(strB))15 slcD := []string{"apple", "peach", "pear"}16 slcB, _ := json.Marshal(slcD)17 fmt.Println(string(slcB))18 mapD := map[string]int{"apple": 5, "lettuce": 7}19 mapB, _ := json.Marshal(mapD)20 fmt.Println(string(mapB))21 res1D := &Response1{22 Fruits: []string{"apple", "peach", "pear"}}23 res1B, _ := json.Marshal(res1D)24 fmt.Println(string(res1B))25 res2D := &Response2{26 Fruits: []string{"apple", "peach", "pear"}}27 res2B, _ := json.Marshal(res2D)28 fmt.Println(string(res2B))29 byt := []byte(`{"num":6.13,"strs":["a","b"]}`)30 var dat map[string]interface{}31 if err := json.Unmarshal(byt, &dat); err != nil {32 panic(err)33 }34 fmt.Println(dat)35 num := dat["num"].(float64)36 fmt.Println(num)37 strs := dat["strs"].([]interface{})38 str1 := strs[0].(string)39 fmt.Println(str1)40 str := `{"page": 1, "fruits": ["apple", "peach"]}`41 res := Response2{}42 json.Unmarshal([]byte(str), &res)43 fmt.Println(res)44 fmt.Println(res.Fruits[0])45 enc := json.NewEncoder(os.Stdout)46 d := map[string]int{"apple": 5,
Parse
Using AI Code Generation
1import (2func main() {3 type Response1 struct {4 }5 bolB, _ := json.Marshal(true)6 fmt.Println(string(bolB))7 intB, _ := json.Marshal(1)8 fmt.Println(string(intB))9 fltB, _ := json.Marshal(2.34)10 fmt.Println(string(fltB))11 strB, _ := json.Marshal("gopher")12 fmt.Println(string(strB))13 slcD := []string{"apple", "peach", "pear"}14 slcB, _ := json.Marshal(slcD)15 fmt.Println(string(slcB))16 mapD := map[string]int{"apple": 5, "lettuce": 7}17 mapB, _ := json.Marshal(mapD)18 fmt.Println(string(mapB))19 res1D := &Response1{20 Fruits: []string{"apple", "peach", "pear"}}21 res1B, _ := json.Marshal(res1D)22 fmt.Println(string(res1B))23 byt := []byte(`{"num":6.13,"strs":["a","b"]}`)24 var dat map[string]interface{}25 if err := json.Unmarshal(byt, &dat); err != nil {26 panic(err)27 }28 fmt.Println(dat)29 num := dat["num"].(float64)30 fmt.Println(num)31 strs := dat["strs"].([]interface{})32 str1 := strs[0].(string)33 fmt.Println(str1)34 str := `{"page": 1, "fruits": ["apple", "peach"]}`35 res := Response1{}36 json.Unmarshal([]byte(str), &res)37 fmt.Println(res)38 fmt.Println(res.Fruits[0])39 enc := json.NewEncoder(os.Stdout)40 d := map[string]int{"apple": 5, "lettuce": 7}41 enc.Encode(d)42}43{"apple":5,"lettuce":7}44{"Page":1,"Fruits":["apple","peach","pear"]}45{1
Parse
Using AI Code Generation
1import (2type Person struct {3}4func main() {5 rdr := strings.NewReader(`{"First":"James","Last":"Bond","Age":20}`)6 json.NewDecoder(rdr).Decode(&p1)7 fmt.Println(p1.First)8 fmt.Println(p1.Last)9 fmt.Println(p1.Age)10}11import (12type Person struct {13}14func main() {15 p1 := Person{"James", "Bond", 20}16 bs, _ := json.Marshal(p1)17 fmt.Println(bs)18 fmt.Printf("%T \n", bs)19 fmt.Println(string(bs))20}21import (22type Person struct {23}24func main() {25 bs := []byte(`{"First":"James","Last":"Bond","Age":20}`)26 json.Unmarshal(bs, &p1)27 fmt.Println(p1.First)28 fmt.Println(p1.Last)29 fmt.Println(p1.Age)30}31import (32type Person struct {33}34func main() {35 p1 := Person{"James", "Bond", 20}36 bs, _ := json.MarshalIndent(p1, "", " ")37 fmt.Println(string(bs))38}39import (40type Person struct {41}42func main() {43 p1 := Person{"James", "Bond", 20}44 p2 := Person{"Miss", "Moneypenny", 19}45 people := []Person{p1, p2}46 fmt.Println(people)47 bs, _ := json.Marshal(people)48 fmt.Println(string(bs))49}
Parse
Using AI Code Generation
1import (2type Person struct {3}4func main() {5 rdr := strings.NewReader(`{"First":"James", "Last":"Bond", "Age":20}`)6 json.NewDecoder(rdr).Decode(&p1)7 fmt.Println(p1.First)8 fmt.Println(p1.Last)9 fmt.Println(p1.Age)10}
Parse
Using AI Code Generation
1import (2type Person struct {3}4func main() {5 r := `[{"First":"James","Last":"Bond","Age":20},{"First":"Miss","Last":"Moneypenny","Age":19}]`6 bs := []byte(r)7 fmt.Printf("%T8 fmt.Printf("%T9 json.Unmarshal(bs, &p1)10 fmt.Println("---------------")11 fmt.Println(p1.First)12 fmt.Println(p1.Last)13 fmt.Println(p1.Age)14}15import (16type Person struct {17}18func main() {19 r := `[{"First":"James","Last":"Bond","Age":20},{"First":"Miss","Last":"Moneypenny","Age":19}]`20 bs := []byte(r)21 fmt.Printf("%T22 fmt.Printf("%T23 json.Unmarshal(bs, &people)24 fmt.Println("---------------")25 fmt.Println(people)26 for i, v := range people {27 fmt.Println("Person Number", i)28 fmt.Println(v.First, v.Last, v.Age)29 }30}31[{James Bond 20 0} {Miss Moneypenny 19 0}]32import (
Parse
Using AI Code Generation
1import (2type Person struct {3}4func main() {5 var p1 = Person{Name: "John", Age: 20}6 fmt.Println("p1 =", p1)7 b, _ := json.Marshal(p1)8 fmt.Println("b =", string(b))9 json.Unmarshal(b, &p2)10 fmt.Println("p2 =", p2)11}12p1 = {John 20}13b = {"Name":"John","Age":20}14p2 = {John 20}
Parse
Using AI Code Generation
1import (2type Student struct {3}4func main() {5 jsonString := `{"Name":"John", "Age":30}`6 err := json.Unmarshal([]byte(jsonString), &student)7 if err != nil {8 fmt.Println(err)9 }10 fmt.Println(student)11}12{John 30}134. json.Marshal() method14import (15type Student struct {16}17func main() {18 student := Student{Name: "John", Age: 30}19 jsonString, err := json.Marshal(student)20 if err != nil {21 fmt.Println(err)22 }23 fmt.Println(string(jsonString))24}25{"Name":"John","Age":30}265. json.MarshalIndent() method27import (28type Student struct {29}30func main() {31 student := Student{Name: "John", Age: 30}32 jsonString, err := json.MarshalIndent(student, "", " ")33 if err != nil {34 fmt.Println(err)35 }36 fmt.Println(string(jsonString))37}38{39}406. json.Decoder() method41import (42type Student struct {43}44func main() {45 jsonString := `{"Name":"John", "Age":30}`
Parse
Using AI Code Generation
1import (2func main() {3 var data = []byte(`{"Name":"John", "Age":30, "City":"New York"}`)4 var result map[string]interface{}5 json.Unmarshal(data, &result)6 fmt.Println(result)7}8import (9func main() {10 var data = map[string]interface{}{11 }12 result, _ := json.Marshal(data)13 fmt.Println(string(result))14}15{"Name":"John","Age":30,"City":"New York"}16import (17func main() {18 var data = map[string]interface{}{19 }20 result, _ := json.MarshalIndent(data, "", " ")21 fmt.Println(string(result))22}23{24}
Parse
Using AI Code Generation
1import (2func main() {3 jsonString := `{"name":"Alex","age":21,"city":"New York"}`4 var data map[string]interface{}5 err := json.Unmarshal([]byte(jsonString), &data)6 if err != nil {7 fmt.Println(err)8 }9}
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!