How to parse JSON extract array [closed] - json

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I work with Go.
I would like to parse a JSON file. But I only need just one array from the JSON file, not all the structure.
This is the JSON file : link
I only need the array of items.
How can I extract just this array from the JSON?

That depends of the definition of your structs. if you want only the array of items, you should unmarshal the main structure and then get the items array.
something like this
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
)
type Structure struct {
Items []Item `json:"items"`
}
type Item struct {
ID int `json:"id"`
Name string `json:"name"`
}
func main() {
data, err := ioutil.ReadFile("myjson.json")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
structure := new(Structure)
json.Unmarshal(data, structure)
theArray := structure.Items
fmt.Println(theArray)
}
The Unmarshal will ignore the fields you don't have defined in your struct. so that means you should add only what you whant to unmarshal
I used this JSON
{
"total_count": 123123,
"items": [
{
"id": 1,
"name": "name1"
},
{
"id": 2,
"name": "name2"
}
]
}

Related

How to convert escaped json into a struct [duplicate]

This question already has answers here:
decode json including json encoded strings
(1 answer)
Unmarshaling a stringified json
(1 answer)
Closed 1 year ago.
I am having trouble converting an escaped json object into a struct.
The main problem I am facing is the escaped json for the sources field.
The following data is how it's being saved.
{
"key": "123",
"sources": "{\"1a\":\"source1a\",\"2b\":\"source2b\",\"3c\":\"source3c\",\"default\":\"sourcex\"}"
}
type config struct {
Key string `json:"key" validate:"required"`
Sources ???? `json:"sources" validate:"required"`
}
I then will have a source value and would like to check if my value is found in the json.
If my value is "1a" return "source1a", etc.
I'm trying to write this in a unit test as well.
Some might do a custom unmarshal method, but I think it's easier just to do two passes:
package main
import (
"encoding/json"
"fmt"
)
const s = `
{
"key": "123",
"sources": "{\"1a\":\"source1a\",\"2b\":\"source2b\",\"3c\":\"source3c\",\"default\":\"sourcex\"}"
}
`
func main() {
var t struct{Key, Sources string}
json.Unmarshal([]byte(s), &t)
m := make(map[string]string)
json.Unmarshal([]byte(t.Sources), &m)
fmt.Println(m) // map[1a:source1a 2b:source2b 3c:source3c default:sourcex]
}

How do I pass through values from an Elasticsearch document in Go?

I'm experimenting with rewriting parts of our system in Go. They're currently written in Python. Some of the data that I want to serve lives in Elasticsearch.
Across our users, we have a few standard fields, but also allow people to create a number of custom fields specific to their environment. E.g., we have a product object that has some common fields like name and price, but we let someone create a field like discount_price or requires_freight to agree with their use case.
In Python, this is easy to accommodate. The JSON is read in, our chosen JSON parser does some reasonable type inference, and we can then return the data after it's processed.
In Go, any data we want to deal with from the Elasticsearch JSON response has to be mapped to a type. Or at least that's my understanding. For example:
import (
"encoding/json"
)
...
type Product struct {
Name string `json:"name"`
Price string `json:"price"`
}
Here's a simplified example of what the data might look like. I've prefixed the names of the nonstandard fields I'd want to pass through with custom:
{
"id": "ABC123",
"name": "Great Product",
"price": 10.99,
"custom_alternate_names": ["Great Product"],
"custom_sellers": [{
"id": "ABC123",
"name": "Great Product LLC",
"emails": ["great#stuff.com"]
}]
}
It would be fine to special case for places where the route actually needs to process or manipulate a custom field. But in most cases, passing through the JSON data unchanged is fine, so the fact we aren't imposing any type mappings for safety isn't adding anything.
Is there a way to set up the struct with an interface (?) that could act as a passthrough for any unmapped fields? Or a way to take the unparsed JSON data and recombine it with the mapped object before the data are returned?
You can do something like this
package main
import (
"encoding/json"
"log"
)
type Product struct {
//embed product to be able to pull the properties without
//requiring a nested object in the json
KnownFields
OtherStuff json.RawMessage
}
//Custom unmarshaller
func (p *Product) UnmarshalJSON(b []byte) error {
var k KnownFields
//unmarshal the known fields
err := json.Unmarshal(b, &k)
if err != nil {
return err
}
p.KnownFields = k
//You can use json.RawMessage or map[string]interface
p.OtherStuff = json.RawMessage(b)
return nil
}
type KnownFields struct {
Name string `json:"name"`
Price json.Number `json:"price"`
}
const JSON = `
{
"id": "ABC123",
"name": "Great Product",
"price": 10.99,
"custom_alternate_names": ["Great Product"],
"custom_sellers": [{
"id": "ABC123",
"name": "Great Product LLC",
"emails": ["great#stuff.com"]
}]
}`
func main() {
var p Product
err := json.Unmarshal([]byte(JSON), &p)
if err != nil {
log.Panic(err)
}
log.Printf("%v", p)
}
If you are going to mutate and marshall the Product you will have to implement a custom marshaller and also you would need to use map[string]interface{} as the OtherStuff to avoid having duplicate entries for the known fields

Using bytes.Buffer with csv.writer [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I'm currently trying to serialize some string slice in a CSV without saving output to a file. I saw some examples using bytes.Buffer but even my the smallest test doesn't work. I don't know how to debug this, the code compiles without warning and doesn't throw error after writer.Flush(). It also works correctly with saving result to a file or piping it directly to standard output
Any help would be appreciated :)
Thx.
PS: the final print is just a test. I know i can use csv.NewWriter(os.stdout) to do so (and it works) but it doesn't fit my needs. I really would like to get the result in a byte array.
package main
import (
"bytes"
"encoding/csv"
"fmt"
)
func main() {
var buffer bytes.Buffer
writer := csv.NewWriter(&buffer)
writer.Write([]string{"1", "2", "3", "4"})
writer.Write([]string{"5", "6", "7", "8"})
defer writer.Flush()
if err := writer.Error(); err != nil {
panic(err)
}
fmt.Println(buffer.Bytes())
}
You are deferring the Flush call, making it execute after the fmt.Println call. Call Flush immediately:
package main
import (
"bytes"
"encoding/csv"
"fmt"
)
func main() {
var buffer bytes.Buffer
writer := csv.NewWriter(&buffer)
writer.Write([]string{"1", "2", "3", "4"})
writer.Write([]string{"5", "6", "7", "8"})
writer.Flush()
if err := writer.Error(); err != nil {
panic(err)
}
fmt.Println(buffer.String())
}
https://play.golang.org/p/BHTyfsuf0tY

How can I copy XML data to JSON whilst renaming the XML fields to a JSONified style [duplicate]

I am struggling to get the correct output from the following code:
package main
import (
"encoding/json"
"fmt"
)
func main() {
var jsonBlob3 = []byte(`[
{"name": "Platypus", "spec": "Monotremata", "id":25 },
{"name": "Quoll", "spec": "Dasyuromorphia", "id":25 }
]`)
type Animal2 struct {
name string
spec string
id uint32
}
var animals []Animal2
err := json.Unmarshal(jsonBlob3, &animals)
if err != nil {
fmt.Println("error:", err)
}
fmt.Printf("%+v\n", animals)
}
Playground snippet
The struct fields are empty when printed. I am sure there is a dumb mistake somewhere but I am still new to Go and I have been stuck at this for hours. Please help.
This has come up so many times. The problem is that only exported fields can be marshaled/unmarshaled.
Export the struct fields by starting them with capital (upper-case) letters.
type Animal2 struct {
Name string
Spec string
Id uint32
}
Try it on the Go Playground.
Note that the JSON text contains the field names with lowercased text, but the json package is "clever" enough to match them. If they would be completely different, you could use struct tags to tell the json package how they are found (or how they should be marshaled) in the JSON text, e.g.:
type Animal2 struct {
Name string `json:"json_name"`
Spec string `json:"specification"`
Id uint32 `json:"some_custom_id"`
}

Json Parsing in Golang

I am trying to parse a json from a third party software. It returns a json like this
{
"top1/dir1": "10",
"top1/dir2": "20",
"top1/dir3": "30",
"top2/diff_val1": "40"
}
JSONLint says this is a valid json. But I could not figure how I can parse this with golang.
The code I used to parse the json file above (to be clear I took the code from another stackoverflow post).
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
)
type mytype []map[string]string
func main() {
var data mytype
file, err := ioutil.ReadFile("t1.json")
if err != nil {
log.Fatal(err)
}
err = json.Unmarshal(file, &data)
if err != nil {
log.Fatal(err)
}
fmt.Println(data)
}
When I do a go run main.go, I get the below error
$ go run main.go
2016/06/19 22:53:57 json: cannot unmarshal object into Go value of type main.mytype
exit status 1
I did try to parse this format with another library - "github.com/Jeffail/gabs", but was unsuccessful. Since this is a valid json, I am pretty sure this can be parsed, but I am not sure how.
There is a Go package with methods for decoding JSON strings.
https://golang.org/pkg/encoding/json/#Unmarshal
Here is an example of usage:
package main
import (
"encoding/json"
"fmt"
)
func main() {
var jsonBlob = []byte(`[
{"Name": "Platypus", "Order": "Monotremata"},
{"Name": "Quoll", "Order": "Dasyuromorphia"}
]`)
type Animal struct {
Name string
Order string
}
var animals []Animal
err := json.Unmarshal(jsonBlob, &animals)
if err != nil {
fmt.Println("error:", err)
}
fmt.Printf("%+v", animals)
}
EDIT: As pointed out by Malik, the type of the value whose pointer you pass is wrong. In this case, your type should be map[string]interface{} (preferably, because a JSON field might not store a string) or map[string]string instead of []map[string]string. The brackets at the beginning are wrong: such would be an array of JSON objects.
It's just that you have a small typo in your program. You've declared mytype as a slice of maps, rather than just a map.
Just change:
type mytype []map[string]string
To:
type mytype map[string]string
See https://play.golang.org/p/pZQl8jV5TC for an example.
Jonathan's answer provides a good example of decoding JSON, and links the relevant package. You don't provide much detail on what exactly is going wrong with your parsing, but if I had to take a guess I would say you're probably not creating an appropriate struct to contain the JSON once it is unmarshalled. Because Go is statically typed, it expects data to adhere to explicitly defined formats.
If you don't want to go to the trouble of defining structs, you could just use an empty interface object, which is sort of a catch all in Go. Simply declare a variable with the type []interface{}, and then pass it into the JSON unmarshal function. Hope this helps!