Need to parse integers in JSON as integers, not floats












-1















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









share|improve this question




















  • 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















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









share|improve this question




















  • 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








-1


1






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









share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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














  • 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












2 Answers
2






active

oldest

votes


















1














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.






share|improve this answer


























  • I appreciate this answer, i'll try it tomorrow.

    – max pleaner
    Nov 22 '18 at 21:49



















0














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("===============")
}
}





share|improve this answer


























  • I appreciate this answer, i'll try it tomorrow.

    – max pleaner
    Nov 22 '18 at 21:49











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
});


}
});














draft saved

draft discarded


















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









1














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.






share|improve this answer


























  • I appreciate this answer, i'll try it tomorrow.

    – max pleaner
    Nov 22 '18 at 21:49
















1














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.






share|improve this answer


























  • I appreciate this answer, i'll try it tomorrow.

    – max pleaner
    Nov 22 '18 at 21:49














1












1








1







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.






share|improve this answer















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.







share|improve this answer














share|improve this answer



share|improve this answer








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



















  • 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













0














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("===============")
}
}





share|improve this answer


























  • I appreciate this answer, i'll try it tomorrow.

    – max pleaner
    Nov 22 '18 at 21:49
















0














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("===============")
}
}





share|improve this answer


























  • I appreciate this answer, i'll try it tomorrow.

    – max pleaner
    Nov 22 '18 at 21:49














0












0








0







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("===============")
}
}





share|improve this answer















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("===============")
}
}






share|improve this answer














share|improve this answer



share|improve this answer








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



















  • 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


















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

A Topological Invariant for $pi_3(U(n))$