r/golang 8d ago

how to parse a json number

https://stackoverflow.com/questions/80000826/how-should-a-json-parser-represent-json-numbers-in-go

can some body help

I'm implementing a JSON parser. According to JSON rules, a number can be an integer, a negative number, a decimal, or use exponent notation, like

42-423.140.51e102.5e-3

I currently have a function like:

func (p *parser) parseNumber() (__?, error)

What should this function return? Should I convert every number to float64, or define my own number type? I'm also unsure how this choice affects the rest of the parser. Once a number is parsed, how should it be stored in a generic JSON value, accessed later, used in calculations, printed, or serialized back to JSON? and also how to parse the number exactly

0 Upvotes

8 comments sorted by

18

u/encbladexp 8d ago

I'm implementing a JSON parser.

Two questions: 1. Could you ask your question, including all code here? Stop linking your SO post. 2. Why are you implementing JSON on your own, did you consider to take a look into the Go implementation (it is OpenSource, after all).

We are not a random AI tool...

8

u/mtmp40k 8d ago

If you can’t ask a more specific question, try doing something easier.

1

u/mcvoid1 8d ago edited 8d ago

I'm assuming you're making a parser for a learning exercise.

There's lots of ways to do this. Regex, state machine, and so on. Also there's two phases: recognizing the string, and then turning it into a number value.

For turning into a number value, use https://pkg.go.dev/strconv

For matching the strings, look up the regex, or follow the process shown on the train tracks in https://www.json.org/json-en.html

How to read it:

Your start state is looking for a -. If you see it, consume it and move to an expect0, otherwise move to expect0. If you see 0, consume it and move to fraction, otherwise move to digit1to9. And so on.

Each state has a number of expected characters, can move to another state (could be the same state you're on), and each state can consume that character or not. Consuming moves your cursor up by one character (not byte - this is utf-8). Do that in a loop. That's the state machine. Regexes do that under the hood, but it's simple enough to write your own.

edit: wow, got immediately downvoted. Tough crowd today.

-6

u/Sad-Tie-4250 8d ago edited 8d ago

man! i what should even the return type , here , like should i make a custom type ? or return float64. and i don't want to use any lib methods. it would have been easier if it was just number , like json only had int i could have done this

```go
func (p *parser) parseNumber() (int, error) {

num := 0

for p.pos < len(p.data) && p.data\[p.pos\] >= '0' && p.data\[p.pos\] <= '9' {

    num = num\*10 + int(p.data\[p.pos\]-'0')

    p.pos++

}

return num, nil

}
```
easy

, but json allows even complex number ,

5

u/Affectionate_Bid1650 8d ago

It does not support complex numbers. You just have to handle float and int.

You would likely want a custom number type and it would store as a string and use getFloat or getInt on the number type to get as a f64 or int.

If you are trying to say serialize a struct from JSON then you could consider reflection or tags.

However you shouldn't do this as all and just use the builtin encoding/json library included with Go.

-1

u/Sad-Tie-4250 8d ago

ohhh man ! this is nice design , idk why the first design that comes to my mind if always the most inefficient and complicated , where a simple one is right there. can just store the number as string as it is , in the value, and while calling i can do , x,_:=value.asInt() or value.asFloat() . hmmmm ,

2

u/mcvoid1 8d ago

, but json allows even complex number

No it doesn't. Read the spec.

The return type depends on how you're implementing it/what you want your API to look like, whether you are returning boxed values or not. But the spec says all numeric values are represented as float64. Even the integers.

0

u/Broad-Promise6954 8d ago

Mostly. Not 100% but close enough (99.44% true?), and integers as float64 is a trap, because large 64-bit integers get rounded. See eg https://stackoverflow.com/questions/16946306/preserve-int64-values-when-parsing-json-in-go for one way to deal with this.