异常JSON解析

I have a JSON String as {1} or possibly {2} and I need to parse it and obtain the integer parsed.

I know I'm doing this incorrectly, but here's what I have thus far:

package main

import (
    "fmt"
    "encoding/json"
)

func main(){
  jsonStr:="{1}"
  jsonData:=[]byte(jsonStr)
  var v uint
  json.Unmarshal(jsonData, &v)
  data:=v
  fmt.Println(data)
}

In this example, the data variable should contain the integer value of 1 or 2 if the jsonStr value is {2}

From my experience with JSON and Go I usually use a struct and pass that into the Unmarshalling function, but i cannot make a struct out of this data response.

I looked at the API Documentation and found no solution for a string parse without a struct

This seemed to work for me:

import "regexp"

re:=regexp.MustCompile("[0-9A-Za-z]+")
val:=re.FindAllString(jsonStr,-1)[0]

Some alternatives to regexes since they are resource heavy and tend to be slower than other solutions, errors are ignored for brevity. In prod they wouldn't be.

package main

import (
    "fmt"
    "strconv"
)

func main() {
    str := "{1}"
    num, _ := strconv.ParseInt(string(str[1]), 10, 64)
    fmt.Println(num)
}

or something more robust that doesn't care about the number of digits in the {} field.

package main

import (
    "fmt"
    "strconv"
)

func main() {
    str := "{341}"
    num, _ := strconv.ParseInt(string(str[1:len(str)-1]), 10, 64)
    fmt.Println(num)
}

Small benchmark image showing how much slower regexes are than other solutions. They should be used when other options are available or if performance isn't an issue/concern. enter image description here

Even something like this will out perform a regex

var n string
for _, r := range str {
    if unicode.IsDigit(r) {
        n += string(r)
    }
}

code for benchmark https://goplay.space/#PLMtSrMTN9k

As noted by commenters, your example strings are not valid JSON since brace-delimited JSON documents must be objects with a list of key-value pairs (e.g. {"x":1}, and numbers are plain (e.g. 2). However, this simple notation of a "brace enclosed integer" could easily be parsed a number of ways, ultimately by checking the syntax of OPEN_BRACE, DIGIT+, CLOSE_BRACE.

The example code below checks that the first rune of a given string is an open brace {, the last is a close brace }, and everything in between can be parsed as an integer using strconv.ParseInt(...):

func main() {
  ss := []string{"{1}", "{2}", "{-123}", "{foo}", "{10", "20}", "30"}
  for _, s := range ss {
    x, err := parseBraceNumber(s)
    fmt.Printf("s=%-10qx=%-10derr=%v
", s, x, err)
  }
  // s="{1}"     x=1         err=<nil>
  // s="{2}"     x=2         err=<nil>
  // s="{-123}"  x=-123      err=<nil>
  // s="{foo}"   x=0         err=invalid brace number "{foo}"
  // s="{10"     x=0         err=invalid brace number "{10"
  // s="20}"     x=0         err=invalid brace number "20}"
  // s="30"      x=0         err=invalid brace number "30"
}

func parseBraceNumber(s string) (int64, error) {
  if len(s) < 3 || s[0] != '{' || s[len(s)-1] != '}' {
    return 0, fmt.Errorf("invalid brace number %q", s)
  }
  x, err := strconv.ParseInt(s[1:len(s)-1], 10, 64)
  if err != nil {
    return 0, fmt.Errorf("invalid brace number %q", s)
  }
  return x, nil
}

Of course, other strategies are possible (e.g. using regular expressions) and ultimately it is up to you to decide what implementation is best for your use case.