I have a JSON array with different value in the array and I don't know how to parse it. Here is an example:
[
{
"firstname": "John",
"lastname": "Doe",
"age": 30
},
{
"companyName": "Doe enterprise",
"location": "NYC",
"numberOfEmployee": 10
}
]
So my JSON is like this, the first element of the array is an user, and the second a company.
I have the equivalent in Elm:
type alias User =
{ firsname : String
, lastname : String
, age : Int
}
type alias Company =
{ companyName : String
, location : String
, numberOfEmployee : Int
}
then: Task.perform FetchFail FetchPass (Http.get decodeData url).
So how do I get my User and Company pass in my FetchPass function ?
There is something like Json.Decode.at but it's for object only.
Here there a way to do something like this ?
decodeData =
Json.at [0] userDecoder
Json.at [1] companyDecoder
Json.at works for array indexes as well. First you'll need a Data type to hold the user and company:
import Json.Decode as Json exposing ((:=))
type alias Data =
{ user : User
, company : Company
}
And you'll need simple decoders for user and company:
userDecoder : Json.Decoder User
userDecoder =
Json.object3 User
("firstname" := Json.string)
("lastname" := Json.string)
("age" := Json.int)
companyDecoder : Json.Decoder Company
companyDecoder =
Json.object3 Company
("companyName" := Json.string)
("location" := Json.string)
("numberOfEmployee" := Json.int)
And finally you can use Json.at to get the values at those array indexes. The difference from your example is that you need to pass a string containing an integer index instead of an int:
dataDecoder : Json.Decoder Data
dataDecoder =
Json.object2 Data
(Json.at ["0"] userDecoder)
(Json.at ["1"] companyDecoder)
Related
This question already has answers here:
JSON single value parsing
(2 answers)
Closed 2 years ago.
I have json object that consists sub object of array. how can I print particular sub object in json.
here is my code
package main
import (
"encoding/json"
"fmt"
)
func main() {
//Simple Employee JSON which we will parse
empArray := `{"meta":[
{
"id": 1,
"name": "Mr. Boss",
"department": "",
"designation": "Director"
},
{
"id": 11,
"name": "Irshad",
"department": "IT",
"designation": "Product Manager"
},
{
"id": 12,
"name": "Pankaj",
"department": "IT",
"designation": "Team Lead"
}
]}`
// Declared an empty interface of type Array
var results []map[string]interface{}
// Unmarshal or Decode the JSON to the interface.
json.Unmarshal([]byte(empArray['meta']), &results)
fmt.Println(results)
}
I'm getting below error while doing soo..
./test.go:35:23: cannot convert empArray['\u0000'] (type byte) to type []byte
./test.go:35:33: invalid character literal (more than one character)
with in the empArray array object, I wanted to print meta object that consists array of employees. Please help me to accomplish this.
You are almost there. Parse the entire document and then pick out the part you want.
var results map[string][]interface{}
json.Unmarshal([]byte(empArray), &results)
fmt.Println(results["meta"])
You should use custom structs:
type Employee struct {
ID int `json:"id"`
Name string `json:"name"`
Department string `json:"department"`
Designation string `json:"designation"`
}
type Employees struct {
Meta []Employee `json:"meta"`
}
When you try to unmarshal the provided string into a Employees var it will read the annotations and know where to place each field. You can find the working example at Golang Playground. I added a string representation to the Employee struct so that fmt.Println output is more redable.
In the case of having an extra nested key ({meta: {data: [...]}}), the types would be as follows:
type Employee struct {
ID int `json:"id"`
Name string `json:"name"`
Department string `json:"department"`
Designation string `json:"designation"`
}
type EmployeesData struct {
Data []Employee `json:"data"`
}
type Employees struct {
Meta EmployeesData `json:"meta"`
}
You can find the working example at Golang Playground too.
NOTE: I do not have context to name the structs properly, so I used Employees and EmployeesData but you should use more descriptive names that help understanding what the whole object represents and not only the meta and data fields.
I'm a Python newbie and I'm trying to write a script to extract json keys by passing the keys dinamically, reading them from a csv.
First of all this is my first post and I'm sorry if my questions are banals and if the code is incomplete but it's just a pseudo code to understand the problem (I hope not to complicate it...)
The following partial code retrieves the values from three key (group, user and id or username) but I'd like to load the objects and key from a csv to make them dinamicals.
Input json
{
"fullname": "The Full Name",
"group": {
"user": {
"id": 1,
"username": "John Doe"
},
"location": {
"x": "1234567",
"y": "9876543"
}
},
"color": {
"code": "ffffff",
"type" : "plastic"
}
}
Python code...
...
url = urlopen(jsonFile)
data = json.loads(url.read())
id = (data["group"]["user"]["id"])
username = (data["group"]["user"]["username"])
...
File.csv loaded into an array. Each line contains one or more keys.
fullname;
group,user,id;
group,user,username;
group,location,x;
group,location,y;
color,code;
The questions are: can I use a variable containing the object or key to be extract?
And how can I specify how many keys there are in the keys array to put them into the data([ ][ ]...) using only one line?
Something like this pseudo code:
...
url = urlopen(jsonFile)
data = json.loads(url.read())
...
keys = line.split(',')
...
# using keys[] to identify the objects and keys
value = (data[keys[0]][keys[1]][keys[2]])
...
But the line value = (data[keys[0]][keys[1]][keys[2]]) should have the exact number of the keys per line read from the csv.
Or I must to make some "if" lines like these?:
...
if len(keys) == 3:
value = (data[keys[0]][keys[1]][keys[2]])
if len(keys) == 2:
value = (data[keys[0]][keys[1]])
...
Many thanks!
I'm not sure I completely understand your question, but I would suggest you to try and play with pandas. It might be as easy as this:
import pandas as pd
df = pd.read_json(<yourJsonFile>, orient='columns')
name = df.fullname[0]
group_user = df.group.user
group_location = df.group.location
color_type = df.color.type
color_code = df.color.code
(Where group_user and group_location will be python dictionaries).
I have this collection :
{
username : "user1",
arr : [
{
name : "test1",
times : 0
},
{
name : "test2",
times : 5
}
]
}
I have an array with some object. This objects have a name and the value times. Now I want to add new objects, if my array doesn't contain them. Example:
I have this two objects with the name "test1" and "test2" already in the collection. I want now to insert the objects "test2", "test3" and "test4". It should only add the object "test3" and "test4" to the array and not "test2" again. The value times doesn't do anything in this case, they should just have the value 0 when it gets insert.
Is there a way to do this with one query?
If you can insert test1, test2,... one by one, then you can do something like this.
db.collection.update(
{username : "user1", 'arr.name': {$ne: 'test2'}},
{$push: {
arr: {'name': 'test2', 'times': 0}
}
})
The $ne condition will prevent the update if the name is already present in arr.
You can now use the addToSet operator that is built just for that: adds a value to an array if it does not exist.
Documentation: https://docs.mongodb.com/manual/reference/operator/update/addToSet/
is it possible to have a dictionary, that contains multiple values for one key?
For example I have multiple IDs (101,102,103,104...) and all of those IDs have some values (colour: green, number: 4, city: New York). I am new to programming and not sure how should I store it.
I was thinking about custom class:
class myClass: NSObject {
var ID: Int
var colour: String
var number: Int
var city: String
init(ID: Int, colour: String, number: Int, city: String) {
self.ID = ID
self.colour = colour
self.number = number
self.city = city
}
}
And the create some variable var myData = myClass() and just everything there, but then how could I access lets say ID 102 and modify its colour?
So my question how to store data provided in my example with an option to be able select specific ID and modify values belonging to that ID.
A dictionary must contain exactly one value for each key. However, that value could be an array, or a dictionary, or an object etc. etc. so that is no practical restriction.
Since instance of classes are stored as references, the dictionary values could be references to class instances. So you can extract the reference to an instance from the dictionary, and then modify the instance. Be aware that anyone holding a reference to the same instance will see the same changes.
Assuming you have two instances of your class
let item101 = MyClass(ID: 101, colour: "red", number: 4, city: "NewYork")
let item102 = MyClass(ID: 102, colour: "green", number: 7, city: "Chicago")
You can store them in a dictionary using the ID as key
let dictionary = [101: item101, 102: item102]
and retrieve a value by ID with
if let id101 = dictionary[101] {
// use id101
} else {
print("ID 101 not found")
}
or you can use an array
let array = [item101, item102]
and get an item by ID with the filter function
let filtered = array.filter{ $0.ID == 102 }
if !filtered.isEmpty {
let id102 = filtered[0]
} else {
print("ID 102 not found")
}
Declare you id with Array and foreach in that ID
var ID: [Int]
I am not expert in Swift and I have been using it for few months to build Mac Apps. I would like to represent in memory a data structure like that of PHP associative arrays but in Swift. Let's imagine that I have a table of data to load in memory with the following fields/records:
ID Surname Name
1 XXX YYY
2 ZZZ WWW
3 JJJ KKK
What I would like to obtain is an associative array like the one I would be able to obtain in PHP:
$arr[1]["Surname"] = "XXX"
$arr[1]["Name"] = "YYY"
$arr[2]["Surname"] = "ZZZ"
$arr[2]["Name"] = "WWW"
I just cannot find the right data structure in Swift to obtain the same result. I tried with the following piece of code:
class resObject: NSObject {
private var cvs = [Int: [String: String]]()
override init() {
self.cvs[0] = ["Name" : "XXX"]
self.cvs[0] = ["Surname" : "YYY"]
self.cvs[1] = ["Name" : "ZZZ"]
self.cvs[1] = ["Surname" : "WWW"]
for (key, arr) in cvs {
let sur = arr["Surname"]
let nam = arr["Name"]
println("Row \(key) - Surname: \(sur), Name: \(nam)")
}
super.init()
}
}
It looks to me pretty close, but it does not work. What I get in the output is the following (I don't care about the "Optional(s)":
Row 0 - Surname: Optional("XXX"), Name: nil
Row 1 - Surname: Optional("ZZZ"), Name: nil
I tried to make some tests in debug and I noticed that the data that are saved in memory are just that of the last key:value pair used (i.e. if I assign Surname first and Name second I get Surname as nil and Name with the correct value).
Please consider that, as in the example, I don't know the data structure when I declare the variable, so I declare it empty and fill it programmatically later.
I don't know if it is just me not declaring the data structure correctly, or if it is Swift that does not allow to do that. Any help will be greatly appreciated.
Thanks a lot.
Regards,
Alessio
One way is a Dictionary of structs. Consider:
struct Person {
var firstName: String
var lastName: String
}
var peopleByID = [ Int: Person ]()
peopleByID[1] = Person(firstName: "First", lastName: "Last")
peopleByID[27] = Person(firstName: "Another", lastName: "LastName")
var myID = 1 // Try changing this to 2 later
if let p = peopleByID[myID] {
println("Found: \(p.firstName) with ID: \(myID)")
}
else {
println("No one found with ID: \(myID)")
}
You can then update the structure:
peopleByID[1].firstName = "XXX"
peopleByID[27].lastName = "ZZZ"
You can iterate freely:
for p in peopleByID.keys {
println("Key: \(p) value: \(peopleByID[p]!.firstName)")
}
Note that a mere array of [Person] isn't so hot, because the IDs:
-- may not be Ints, but are often Strings
-- even if they remain Ints, an array takes up storage in proportion to the highest numbered index, whereas a Dictionary only takes up storage in proportion to the number of stored objects. Imagine storing just two ID's: 523123, and 2467411.
EDIT
It seems like you don't know the attributes ahead of time that will go into each Person object. That's odd, but you should then do:
struct Person {
var attributes = [String : String]() // A dictionary of String keys and String values
}
var peopleByID = [ Int : Person ]()
// and then:
var p1 = Person()
var p2 = Person()
p1.attributes["Surname"] = "Somename"
p1.attributes["Name"] = "Firstname"
p2.attributes["Address"] = "123 Main St."
peopleByID[1] = p1
peopleByID[2] = p2
if let person1 = peopleByID[1] {
println(person1.attributes["Surname"]!)
for attrKey in person1.attributes.keys {
println("Key: \(attrKey) value: \(person1.attributes[attrKey]!)")
}
}