Need to parse integers in JSON as integers, not floats
First of all let me explain the problem.
I have a stream of JSON records coming into my Golang app. It basically forwards these to a data store (InfluxDB). There are some integer values in the JSON, and also some float values. It is essential that these get forwarded to the data store with the original data type. If they don't, there will be type conflicts and the write operation will fail.
The Ruby JSON parser has no trouble doing this:
require 'json'
obj = { "a" => 123, "b" => 12.3 }
parsed = JSON.parse(obj.to_json)
print parsed["a"].class # => Integer
print parsed["b"].class # => Float
The encoding/json
package in Golang, does have some trouble (all numbers are parsed as floats):
package main
import "encoding/json"
import "fmt"
func main () {
str := "{"a":123,"b":12.3}"
var parsed map[string]interface{}
json.Unmarshal(byte(str), &parsed)
for key, val := range parsed {
switch val.(type) {
case int:
fmt.Println("int type: ", key)
case float64:
fmt.Println("float type: ", key)
default:
fmt.Println("unknown type: ", key)
}
}
}
Which prints:
float type: a
float type: b
I need a way to parse ints as ints, and floats as floats, in the way the Ruby JSON parser does.
It is not feasible in this case to parse everything as strings and check whether or not there is a decimal. Certain values come in as strings such as "123" and I need to push those as strings.
I do not have structs for the parsed objects, nor is that an option. The golang app doesn't actually care about the schema and just forwards the input as it receives it.
I tried the approach outlined here: Other ways of verifying reflect.Type for int and float64 (using reflect
) but it did not accurately identify the int:
t := reflect.TypeOf(parsed["a"])
k := t.Kind()
k == reflect.Int // false
k == reflect.Float64 // true
json go
|
show 3 more comments
First of all let me explain the problem.
I have a stream of JSON records coming into my Golang app. It basically forwards these to a data store (InfluxDB). There are some integer values in the JSON, and also some float values. It is essential that these get forwarded to the data store with the original data type. If they don't, there will be type conflicts and the write operation will fail.
The Ruby JSON parser has no trouble doing this:
require 'json'
obj = { "a" => 123, "b" => 12.3 }
parsed = JSON.parse(obj.to_json)
print parsed["a"].class # => Integer
print parsed["b"].class # => Float
The encoding/json
package in Golang, does have some trouble (all numbers are parsed as floats):
package main
import "encoding/json"
import "fmt"
func main () {
str := "{"a":123,"b":12.3}"
var parsed map[string]interface{}
json.Unmarshal(byte(str), &parsed)
for key, val := range parsed {
switch val.(type) {
case int:
fmt.Println("int type: ", key)
case float64:
fmt.Println("float type: ", key)
default:
fmt.Println("unknown type: ", key)
}
}
}
Which prints:
float type: a
float type: b
I need a way to parse ints as ints, and floats as floats, in the way the Ruby JSON parser does.
It is not feasible in this case to parse everything as strings and check whether or not there is a decimal. Certain values come in as strings such as "123" and I need to push those as strings.
I do not have structs for the parsed objects, nor is that an option. The golang app doesn't actually care about the schema and just forwards the input as it receives it.
I tried the approach outlined here: Other ways of verifying reflect.Type for int and float64 (using reflect
) but it did not accurately identify the int:
t := reflect.TypeOf(parsed["a"])
k := t.Kind()
k == reflect.Int // false
k == reflect.Float64 // true
json go
1
You should unmarshal into a struct where your fields are properly typed and defined. If you really can't do this, and you're just passing the data on somewhere else, then why are you unmarshaling the JSON at all?
– Michael Hampton
Nov 22 '18 at 1:46
@MichaelHampton there is no reason for me to do this, besides this one case of distinguishing int and float. I typecheck each of the values of the JSON objects that they are either float/string/int. The only thing missing is the ability to distinguish int and float.
– max pleaner
Nov 22 '18 at 1:48
@MichaelHampton I'm unmarshalling into objects which can be passed to the data store by the client library.
– max pleaner
Nov 22 '18 at 1:49
1
encoding/json will happily unmarshal an int into an int field of a struct. It doesn't really make a lot of sense why you aren't doing this. Are you using the right language? Go might not be right for whatever you're trying to do.
– Michael Hampton
Nov 22 '18 at 1:51
1
Only 80? I have a Go project with 365 such structs (and adding more regularly). I know exactly how non-trivial it is. But it's a whole lot better than trying to abuse reflection like this. So I speak from experience when I ask if you're using the right language.
– Michael Hampton
Nov 22 '18 at 2:06
|
show 3 more comments
First of all let me explain the problem.
I have a stream of JSON records coming into my Golang app. It basically forwards these to a data store (InfluxDB). There are some integer values in the JSON, and also some float values. It is essential that these get forwarded to the data store with the original data type. If they don't, there will be type conflicts and the write operation will fail.
The Ruby JSON parser has no trouble doing this:
require 'json'
obj = { "a" => 123, "b" => 12.3 }
parsed = JSON.parse(obj.to_json)
print parsed["a"].class # => Integer
print parsed["b"].class # => Float
The encoding/json
package in Golang, does have some trouble (all numbers are parsed as floats):
package main
import "encoding/json"
import "fmt"
func main () {
str := "{"a":123,"b":12.3}"
var parsed map[string]interface{}
json.Unmarshal(byte(str), &parsed)
for key, val := range parsed {
switch val.(type) {
case int:
fmt.Println("int type: ", key)
case float64:
fmt.Println("float type: ", key)
default:
fmt.Println("unknown type: ", key)
}
}
}
Which prints:
float type: a
float type: b
I need a way to parse ints as ints, and floats as floats, in the way the Ruby JSON parser does.
It is not feasible in this case to parse everything as strings and check whether or not there is a decimal. Certain values come in as strings such as "123" and I need to push those as strings.
I do not have structs for the parsed objects, nor is that an option. The golang app doesn't actually care about the schema and just forwards the input as it receives it.
I tried the approach outlined here: Other ways of verifying reflect.Type for int and float64 (using reflect
) but it did not accurately identify the int:
t := reflect.TypeOf(parsed["a"])
k := t.Kind()
k == reflect.Int // false
k == reflect.Float64 // true
json go
First of all let me explain the problem.
I have a stream of JSON records coming into my Golang app. It basically forwards these to a data store (InfluxDB). There are some integer values in the JSON, and also some float values. It is essential that these get forwarded to the data store with the original data type. If they don't, there will be type conflicts and the write operation will fail.
The Ruby JSON parser has no trouble doing this:
require 'json'
obj = { "a" => 123, "b" => 12.3 }
parsed = JSON.parse(obj.to_json)
print parsed["a"].class # => Integer
print parsed["b"].class # => Float
The encoding/json
package in Golang, does have some trouble (all numbers are parsed as floats):
package main
import "encoding/json"
import "fmt"
func main () {
str := "{"a":123,"b":12.3}"
var parsed map[string]interface{}
json.Unmarshal(byte(str), &parsed)
for key, val := range parsed {
switch val.(type) {
case int:
fmt.Println("int type: ", key)
case float64:
fmt.Println("float type: ", key)
default:
fmt.Println("unknown type: ", key)
}
}
}
Which prints:
float type: a
float type: b
I need a way to parse ints as ints, and floats as floats, in the way the Ruby JSON parser does.
It is not feasible in this case to parse everything as strings and check whether or not there is a decimal. Certain values come in as strings such as "123" and I need to push those as strings.
I do not have structs for the parsed objects, nor is that an option. The golang app doesn't actually care about the schema and just forwards the input as it receives it.
I tried the approach outlined here: Other ways of verifying reflect.Type for int and float64 (using reflect
) but it did not accurately identify the int:
t := reflect.TypeOf(parsed["a"])
k := t.Kind()
k == reflect.Int // false
k == reflect.Float64 // true
json go
json go
edited Nov 22 '18 at 1:32
max pleaner
asked Nov 22 '18 at 1:09
max pleanermax pleaner
13.9k42167
13.9k42167
1
You should unmarshal into a struct where your fields are properly typed and defined. If you really can't do this, and you're just passing the data on somewhere else, then why are you unmarshaling the JSON at all?
– Michael Hampton
Nov 22 '18 at 1:46
@MichaelHampton there is no reason for me to do this, besides this one case of distinguishing int and float. I typecheck each of the values of the JSON objects that they are either float/string/int. The only thing missing is the ability to distinguish int and float.
– max pleaner
Nov 22 '18 at 1:48
@MichaelHampton I'm unmarshalling into objects which can be passed to the data store by the client library.
– max pleaner
Nov 22 '18 at 1:49
1
encoding/json will happily unmarshal an int into an int field of a struct. It doesn't really make a lot of sense why you aren't doing this. Are you using the right language? Go might not be right for whatever you're trying to do.
– Michael Hampton
Nov 22 '18 at 1:51
1
Only 80? I have a Go project with 365 such structs (and adding more regularly). I know exactly how non-trivial it is. But it's a whole lot better than trying to abuse reflection like this. So I speak from experience when I ask if you're using the right language.
– Michael Hampton
Nov 22 '18 at 2:06
|
show 3 more comments
1
You should unmarshal into a struct where your fields are properly typed and defined. If you really can't do this, and you're just passing the data on somewhere else, then why are you unmarshaling the JSON at all?
– Michael Hampton
Nov 22 '18 at 1:46
@MichaelHampton there is no reason for me to do this, besides this one case of distinguishing int and float. I typecheck each of the values of the JSON objects that they are either float/string/int. The only thing missing is the ability to distinguish int and float.
– max pleaner
Nov 22 '18 at 1:48
@MichaelHampton I'm unmarshalling into objects which can be passed to the data store by the client library.
– max pleaner
Nov 22 '18 at 1:49
1
encoding/json will happily unmarshal an int into an int field of a struct. It doesn't really make a lot of sense why you aren't doing this. Are you using the right language? Go might not be right for whatever you're trying to do.
– Michael Hampton
Nov 22 '18 at 1:51
1
Only 80? I have a Go project with 365 such structs (and adding more regularly). I know exactly how non-trivial it is. But it's a whole lot better than trying to abuse reflection like this. So I speak from experience when I ask if you're using the right language.
– Michael Hampton
Nov 22 '18 at 2:06
1
1
You should unmarshal into a struct where your fields are properly typed and defined. If you really can't do this, and you're just passing the data on somewhere else, then why are you unmarshaling the JSON at all?
– Michael Hampton
Nov 22 '18 at 1:46
You should unmarshal into a struct where your fields are properly typed and defined. If you really can't do this, and you're just passing the data on somewhere else, then why are you unmarshaling the JSON at all?
– Michael Hampton
Nov 22 '18 at 1:46
@MichaelHampton there is no reason for me to do this, besides this one case of distinguishing int and float. I typecheck each of the values of the JSON objects that they are either float/string/int. The only thing missing is the ability to distinguish int and float.
– max pleaner
Nov 22 '18 at 1:48
@MichaelHampton there is no reason for me to do this, besides this one case of distinguishing int and float. I typecheck each of the values of the JSON objects that they are either float/string/int. The only thing missing is the ability to distinguish int and float.
– max pleaner
Nov 22 '18 at 1:48
@MichaelHampton I'm unmarshalling into objects which can be passed to the data store by the client library.
– max pleaner
Nov 22 '18 at 1:49
@MichaelHampton I'm unmarshalling into objects which can be passed to the data store by the client library.
– max pleaner
Nov 22 '18 at 1:49
1
1
encoding/json will happily unmarshal an int into an int field of a struct. It doesn't really make a lot of sense why you aren't doing this. Are you using the right language? Go might not be right for whatever you're trying to do.
– Michael Hampton
Nov 22 '18 at 1:51
encoding/json will happily unmarshal an int into an int field of a struct. It doesn't really make a lot of sense why you aren't doing this. Are you using the right language? Go might not be right for whatever you're trying to do.
– Michael Hampton
Nov 22 '18 at 1:51
1
1
Only 80? I have a Go project with 365 such structs (and adding more regularly). I know exactly how non-trivial it is. But it's a whole lot better than trying to abuse reflection like this. So I speak from experience when I ask if you're using the right language.
– Michael Hampton
Nov 22 '18 at 2:06
Only 80? I have a Go project with 365 such structs (and adding more regularly). I know exactly how non-trivial it is. But it's a whole lot better than trying to abuse reflection like this. So I speak from experience when I ask if you're using the right language.
– Michael Hampton
Nov 22 '18 at 2:06
|
show 3 more comments
2 Answers
2
active
oldest
votes
For example, Ruby JSON number types using the general Go mechanism for custom JSON values,
package main
import (
"encoding/json"
"fmt"
"strconv"
)
func main() {
str := `{"a":123,"b":12.3,"c":"123","d":"12.3","e":true}`
var raw map[string]json.RawMessage
err := json.Unmarshal(byte(str), &raw)
if err != nil {
panic(err)
}
parsed := make(map[string]interface{}, len(raw))
for key, val := range raw {
s := string(val)
i, err := strconv.ParseInt(s, 10, 64)
if err == nil {
parsed[key] = i
continue
}
f, err := strconv.ParseFloat(s, 64)
if err == nil {
parsed[key] = f
continue
}
var v interface{}
err = json.Unmarshal(val, &v)
if err == nil {
parsed[key] = v
continue
}
parsed[key] = val
}
for key, val := range parsed {
fmt.Printf("%T: %v %vn", val, key, val)
}
}
Playground: https://play.golang.org/p/VmG8IZV4CG_Y
Output:
int64: a 123
float64: b 12.3
string: c 123
string: d 12.3
bool: e true
Another example, Ruby JSON number types using the Go json.Number
type,
package main
import (
"encoding/json"
"fmt"
"strings"
)
func main() {
str := `{"a":123,"b":12.3,"c":"123","d":"12.3","e":true}`
var parsed map[string]interface{}
d := json.NewDecoder(strings.NewReader(str))
d.UseNumber()
err := d.Decode(&parsed)
if err != nil {
panic(err)
}
for key, val := range parsed {
n, ok := val.(json.Number)
if !ok {
continue
}
if i, err := n.Int64(); err == nil {
parsed[key] = i
continue
}
if f, err := n.Float64(); err == nil {
parsed[key] = f
continue
}
}
for key, val := range parsed {
fmt.Printf("%T: %v %vn", val, key, val)
}
}
Playground: https://play.golang.org/p/Hk_Wb0EM-aY
Output:
int64: a 123
float64: b 12.3
string: c 123
string: d 12.3
bool: e true
A working version of @ShudiptaSharma's suggestion.
I appreciate this answer, i'll try it tomorrow.
– max pleaner
Nov 22 '18 at 21:49
add a comment |
There exists a type json.Number
in json package which has 3 format functions String() string
, Float64() (float64, error)
and Int64() (int64, error)
. We can use them to parse integer and float type.
So, I handle json integer parsing in this way:
package main
import "encoding/json"
import "fmt"
import "strings"
import (
"reflect"
)
func main () {
str := "{"a":123,"b":12.3}"
var parsed map[string]interface{}
d := json.NewDecoder(strings.NewReader(str))
d.UseNumber()
fmt.Println(d.Decode(&parsed))
for key, val := range parsed {
fmt.Println(reflect.TypeOf(val))
fmt.Printf("decoded to %#vn", val)
switch val.(type) {
case json.Number:
if n, err := val.(json.Number).Int64(); err == nil {
fmt.Println("int64 type: ", key, n)
} else if f, err := val.(json.Number).Float64(); err == nil {
fmt.Println("float64 type: ", key, f)
} else {
fmt.Println("string type: ", key, val)
}
default:
fmt.Println("unknown type: ", key, val)
}
fmt.Println("===============")
}
}
I appreciate this answer, i'll try it tomorrow.
– max pleaner
Nov 22 '18 at 21:49
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53422587%2fneed-to-parse-integers-in-json-as-integers-not-floats%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
For example, Ruby JSON number types using the general Go mechanism for custom JSON values,
package main
import (
"encoding/json"
"fmt"
"strconv"
)
func main() {
str := `{"a":123,"b":12.3,"c":"123","d":"12.3","e":true}`
var raw map[string]json.RawMessage
err := json.Unmarshal(byte(str), &raw)
if err != nil {
panic(err)
}
parsed := make(map[string]interface{}, len(raw))
for key, val := range raw {
s := string(val)
i, err := strconv.ParseInt(s, 10, 64)
if err == nil {
parsed[key] = i
continue
}
f, err := strconv.ParseFloat(s, 64)
if err == nil {
parsed[key] = f
continue
}
var v interface{}
err = json.Unmarshal(val, &v)
if err == nil {
parsed[key] = v
continue
}
parsed[key] = val
}
for key, val := range parsed {
fmt.Printf("%T: %v %vn", val, key, val)
}
}
Playground: https://play.golang.org/p/VmG8IZV4CG_Y
Output:
int64: a 123
float64: b 12.3
string: c 123
string: d 12.3
bool: e true
Another example, Ruby JSON number types using the Go json.Number
type,
package main
import (
"encoding/json"
"fmt"
"strings"
)
func main() {
str := `{"a":123,"b":12.3,"c":"123","d":"12.3","e":true}`
var parsed map[string]interface{}
d := json.NewDecoder(strings.NewReader(str))
d.UseNumber()
err := d.Decode(&parsed)
if err != nil {
panic(err)
}
for key, val := range parsed {
n, ok := val.(json.Number)
if !ok {
continue
}
if i, err := n.Int64(); err == nil {
parsed[key] = i
continue
}
if f, err := n.Float64(); err == nil {
parsed[key] = f
continue
}
}
for key, val := range parsed {
fmt.Printf("%T: %v %vn", val, key, val)
}
}
Playground: https://play.golang.org/p/Hk_Wb0EM-aY
Output:
int64: a 123
float64: b 12.3
string: c 123
string: d 12.3
bool: e true
A working version of @ShudiptaSharma's suggestion.
I appreciate this answer, i'll try it tomorrow.
– max pleaner
Nov 22 '18 at 21:49
add a comment |
For example, Ruby JSON number types using the general Go mechanism for custom JSON values,
package main
import (
"encoding/json"
"fmt"
"strconv"
)
func main() {
str := `{"a":123,"b":12.3,"c":"123","d":"12.3","e":true}`
var raw map[string]json.RawMessage
err := json.Unmarshal(byte(str), &raw)
if err != nil {
panic(err)
}
parsed := make(map[string]interface{}, len(raw))
for key, val := range raw {
s := string(val)
i, err := strconv.ParseInt(s, 10, 64)
if err == nil {
parsed[key] = i
continue
}
f, err := strconv.ParseFloat(s, 64)
if err == nil {
parsed[key] = f
continue
}
var v interface{}
err = json.Unmarshal(val, &v)
if err == nil {
parsed[key] = v
continue
}
parsed[key] = val
}
for key, val := range parsed {
fmt.Printf("%T: %v %vn", val, key, val)
}
}
Playground: https://play.golang.org/p/VmG8IZV4CG_Y
Output:
int64: a 123
float64: b 12.3
string: c 123
string: d 12.3
bool: e true
Another example, Ruby JSON number types using the Go json.Number
type,
package main
import (
"encoding/json"
"fmt"
"strings"
)
func main() {
str := `{"a":123,"b":12.3,"c":"123","d":"12.3","e":true}`
var parsed map[string]interface{}
d := json.NewDecoder(strings.NewReader(str))
d.UseNumber()
err := d.Decode(&parsed)
if err != nil {
panic(err)
}
for key, val := range parsed {
n, ok := val.(json.Number)
if !ok {
continue
}
if i, err := n.Int64(); err == nil {
parsed[key] = i
continue
}
if f, err := n.Float64(); err == nil {
parsed[key] = f
continue
}
}
for key, val := range parsed {
fmt.Printf("%T: %v %vn", val, key, val)
}
}
Playground: https://play.golang.org/p/Hk_Wb0EM-aY
Output:
int64: a 123
float64: b 12.3
string: c 123
string: d 12.3
bool: e true
A working version of @ShudiptaSharma's suggestion.
I appreciate this answer, i'll try it tomorrow.
– max pleaner
Nov 22 '18 at 21:49
add a comment |
For example, Ruby JSON number types using the general Go mechanism for custom JSON values,
package main
import (
"encoding/json"
"fmt"
"strconv"
)
func main() {
str := `{"a":123,"b":12.3,"c":"123","d":"12.3","e":true}`
var raw map[string]json.RawMessage
err := json.Unmarshal(byte(str), &raw)
if err != nil {
panic(err)
}
parsed := make(map[string]interface{}, len(raw))
for key, val := range raw {
s := string(val)
i, err := strconv.ParseInt(s, 10, 64)
if err == nil {
parsed[key] = i
continue
}
f, err := strconv.ParseFloat(s, 64)
if err == nil {
parsed[key] = f
continue
}
var v interface{}
err = json.Unmarshal(val, &v)
if err == nil {
parsed[key] = v
continue
}
parsed[key] = val
}
for key, val := range parsed {
fmt.Printf("%T: %v %vn", val, key, val)
}
}
Playground: https://play.golang.org/p/VmG8IZV4CG_Y
Output:
int64: a 123
float64: b 12.3
string: c 123
string: d 12.3
bool: e true
Another example, Ruby JSON number types using the Go json.Number
type,
package main
import (
"encoding/json"
"fmt"
"strings"
)
func main() {
str := `{"a":123,"b":12.3,"c":"123","d":"12.3","e":true}`
var parsed map[string]interface{}
d := json.NewDecoder(strings.NewReader(str))
d.UseNumber()
err := d.Decode(&parsed)
if err != nil {
panic(err)
}
for key, val := range parsed {
n, ok := val.(json.Number)
if !ok {
continue
}
if i, err := n.Int64(); err == nil {
parsed[key] = i
continue
}
if f, err := n.Float64(); err == nil {
parsed[key] = f
continue
}
}
for key, val := range parsed {
fmt.Printf("%T: %v %vn", val, key, val)
}
}
Playground: https://play.golang.org/p/Hk_Wb0EM-aY
Output:
int64: a 123
float64: b 12.3
string: c 123
string: d 12.3
bool: e true
A working version of @ShudiptaSharma's suggestion.
For example, Ruby JSON number types using the general Go mechanism for custom JSON values,
package main
import (
"encoding/json"
"fmt"
"strconv"
)
func main() {
str := `{"a":123,"b":12.3,"c":"123","d":"12.3","e":true}`
var raw map[string]json.RawMessage
err := json.Unmarshal(byte(str), &raw)
if err != nil {
panic(err)
}
parsed := make(map[string]interface{}, len(raw))
for key, val := range raw {
s := string(val)
i, err := strconv.ParseInt(s, 10, 64)
if err == nil {
parsed[key] = i
continue
}
f, err := strconv.ParseFloat(s, 64)
if err == nil {
parsed[key] = f
continue
}
var v interface{}
err = json.Unmarshal(val, &v)
if err == nil {
parsed[key] = v
continue
}
parsed[key] = val
}
for key, val := range parsed {
fmt.Printf("%T: %v %vn", val, key, val)
}
}
Playground: https://play.golang.org/p/VmG8IZV4CG_Y
Output:
int64: a 123
float64: b 12.3
string: c 123
string: d 12.3
bool: e true
Another example, Ruby JSON number types using the Go json.Number
type,
package main
import (
"encoding/json"
"fmt"
"strings"
)
func main() {
str := `{"a":123,"b":12.3,"c":"123","d":"12.3","e":true}`
var parsed map[string]interface{}
d := json.NewDecoder(strings.NewReader(str))
d.UseNumber()
err := d.Decode(&parsed)
if err != nil {
panic(err)
}
for key, val := range parsed {
n, ok := val.(json.Number)
if !ok {
continue
}
if i, err := n.Int64(); err == nil {
parsed[key] = i
continue
}
if f, err := n.Float64(); err == nil {
parsed[key] = f
continue
}
}
for key, val := range parsed {
fmt.Printf("%T: %v %vn", val, key, val)
}
}
Playground: https://play.golang.org/p/Hk_Wb0EM-aY
Output:
int64: a 123
float64: b 12.3
string: c 123
string: d 12.3
bool: e true
A working version of @ShudiptaSharma's suggestion.
edited Nov 23 '18 at 18:40
answered Nov 22 '18 at 3:43
peterSOpeterSO
95.9k14160177
95.9k14160177
I appreciate this answer, i'll try it tomorrow.
– max pleaner
Nov 22 '18 at 21:49
add a comment |
I appreciate this answer, i'll try it tomorrow.
– max pleaner
Nov 22 '18 at 21:49
I appreciate this answer, i'll try it tomorrow.
– max pleaner
Nov 22 '18 at 21:49
I appreciate this answer, i'll try it tomorrow.
– max pleaner
Nov 22 '18 at 21:49
add a comment |
There exists a type json.Number
in json package which has 3 format functions String() string
, Float64() (float64, error)
and Int64() (int64, error)
. We can use them to parse integer and float type.
So, I handle json integer parsing in this way:
package main
import "encoding/json"
import "fmt"
import "strings"
import (
"reflect"
)
func main () {
str := "{"a":123,"b":12.3}"
var parsed map[string]interface{}
d := json.NewDecoder(strings.NewReader(str))
d.UseNumber()
fmt.Println(d.Decode(&parsed))
for key, val := range parsed {
fmt.Println(reflect.TypeOf(val))
fmt.Printf("decoded to %#vn", val)
switch val.(type) {
case json.Number:
if n, err := val.(json.Number).Int64(); err == nil {
fmt.Println("int64 type: ", key, n)
} else if f, err := val.(json.Number).Float64(); err == nil {
fmt.Println("float64 type: ", key, f)
} else {
fmt.Println("string type: ", key, val)
}
default:
fmt.Println("unknown type: ", key, val)
}
fmt.Println("===============")
}
}
I appreciate this answer, i'll try it tomorrow.
– max pleaner
Nov 22 '18 at 21:49
add a comment |
There exists a type json.Number
in json package which has 3 format functions String() string
, Float64() (float64, error)
and Int64() (int64, error)
. We can use them to parse integer and float type.
So, I handle json integer parsing in this way:
package main
import "encoding/json"
import "fmt"
import "strings"
import (
"reflect"
)
func main () {
str := "{"a":123,"b":12.3}"
var parsed map[string]interface{}
d := json.NewDecoder(strings.NewReader(str))
d.UseNumber()
fmt.Println(d.Decode(&parsed))
for key, val := range parsed {
fmt.Println(reflect.TypeOf(val))
fmt.Printf("decoded to %#vn", val)
switch val.(type) {
case json.Number:
if n, err := val.(json.Number).Int64(); err == nil {
fmt.Println("int64 type: ", key, n)
} else if f, err := val.(json.Number).Float64(); err == nil {
fmt.Println("float64 type: ", key, f)
} else {
fmt.Println("string type: ", key, val)
}
default:
fmt.Println("unknown type: ", key, val)
}
fmt.Println("===============")
}
}
I appreciate this answer, i'll try it tomorrow.
– max pleaner
Nov 22 '18 at 21:49
add a comment |
There exists a type json.Number
in json package which has 3 format functions String() string
, Float64() (float64, error)
and Int64() (int64, error)
. We can use them to parse integer and float type.
So, I handle json integer parsing in this way:
package main
import "encoding/json"
import "fmt"
import "strings"
import (
"reflect"
)
func main () {
str := "{"a":123,"b":12.3}"
var parsed map[string]interface{}
d := json.NewDecoder(strings.NewReader(str))
d.UseNumber()
fmt.Println(d.Decode(&parsed))
for key, val := range parsed {
fmt.Println(reflect.TypeOf(val))
fmt.Printf("decoded to %#vn", val)
switch val.(type) {
case json.Number:
if n, err := val.(json.Number).Int64(); err == nil {
fmt.Println("int64 type: ", key, n)
} else if f, err := val.(json.Number).Float64(); err == nil {
fmt.Println("float64 type: ", key, f)
} else {
fmt.Println("string type: ", key, val)
}
default:
fmt.Println("unknown type: ", key, val)
}
fmt.Println("===============")
}
}
There exists a type json.Number
in json package which has 3 format functions String() string
, Float64() (float64, error)
and Int64() (int64, error)
. We can use them to parse integer and float type.
So, I handle json integer parsing in this way:
package main
import "encoding/json"
import "fmt"
import "strings"
import (
"reflect"
)
func main () {
str := "{"a":123,"b":12.3}"
var parsed map[string]interface{}
d := json.NewDecoder(strings.NewReader(str))
d.UseNumber()
fmt.Println(d.Decode(&parsed))
for key, val := range parsed {
fmt.Println(reflect.TypeOf(val))
fmt.Printf("decoded to %#vn", val)
switch val.(type) {
case json.Number:
if n, err := val.(json.Number).Int64(); err == nil {
fmt.Println("int64 type: ", key, n)
} else if f, err := val.(json.Number).Float64(); err == nil {
fmt.Println("float64 type: ", key, f)
} else {
fmt.Println("string type: ", key, val)
}
default:
fmt.Println("unknown type: ", key, val)
}
fmt.Println("===============")
}
}
edited Nov 22 '18 at 5:49
answered Nov 22 '18 at 5:44
Shudipta SharmaShudipta Sharma
1,185413
1,185413
I appreciate this answer, i'll try it tomorrow.
– max pleaner
Nov 22 '18 at 21:49
add a comment |
I appreciate this answer, i'll try it tomorrow.
– max pleaner
Nov 22 '18 at 21:49
I appreciate this answer, i'll try it tomorrow.
– max pleaner
Nov 22 '18 at 21:49
I appreciate this answer, i'll try it tomorrow.
– max pleaner
Nov 22 '18 at 21:49
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53422587%2fneed-to-parse-integers-in-json-as-integers-not-floats%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
You should unmarshal into a struct where your fields are properly typed and defined. If you really can't do this, and you're just passing the data on somewhere else, then why are you unmarshaling the JSON at all?
– Michael Hampton
Nov 22 '18 at 1:46
@MichaelHampton there is no reason for me to do this, besides this one case of distinguishing int and float. I typecheck each of the values of the JSON objects that they are either float/string/int. The only thing missing is the ability to distinguish int and float.
– max pleaner
Nov 22 '18 at 1:48
@MichaelHampton I'm unmarshalling into objects which can be passed to the data store by the client library.
– max pleaner
Nov 22 '18 at 1:49
1
encoding/json will happily unmarshal an int into an int field of a struct. It doesn't really make a lot of sense why you aren't doing this. Are you using the right language? Go might not be right for whatever you're trying to do.
– Michael Hampton
Nov 22 '18 at 1:51
1
Only 80? I have a Go project with 365 such structs (and adding more regularly). I know exactly how non-trivial it is. But it's a whole lot better than trying to abuse reflection like this. So I speak from experience when I ask if you're using the right language.
– Michael Hampton
Nov 22 '18 at 2:06