What is the meaning of []json.Rawmessage. Its within this structure here:
type Request struct {
Jsonrpc string `json:"jsonrpc"`
Method string `json:"method"`
Params []json.RawMessage `json:"params"`
ID interface{} `json:"id"`
}
I know its a slice of type json. I do not understand what the .RawMessage is referring to. I tried looking it up in both golang tour and my golang book. Also ultimately I know Params is type []json.Rawmessage being bundled into another type called Request
Futhermore:
What is going on with these segments json:"jsonrpc". Is a string literal somehow being attached to var? Again this is not in golang tour or my golang book. Thanks for your time.
[] is defining a slice
json is the package import name (from your import statement above)
RawMessage is the type within the package. In this case for a []byte type.
json:"params" is a field tag. The json package reads it with reflection and determines what name to use for json.
Most of the time time you need to look in to the package doc rather than some book and the online tour.
The json:"jsonrpc" is a struct tag.
For this specific case the json.Marshal function will read that struct tag and return the JSON field name with the given value. For more about "encoding/json" struct tags usage: https://golang.org/pkg/encoding/json/#Marshal
For RawMessage, you can read more about it here https://golang.org/pkg/encoding/json/#RawMessage
type RawMessage []byte
Normally I use it when having a "generic" kind of JSON object that don't need to be process right the way (maybe I just send them to another service, or I will unmarshall it later depending on conditions). For example (I will use your Request struct):
jsonString := `[
{
"id": 123,
"method": "getSomething",
"params": [{"A": 1, "B": 2}]
}
{
"id": 123,
"method": "getSomethingElse",
"params": [{"C": 1, "D": 2}]
}
]`
With this processing code:
var requests []Request
json.Unmarshal([]byte(jsonString), &requests)
// if no error, you will have 2 items in requests
// requests[0].Params[0] is equal to []byte(`{"A": 1, "B": 2}`)
// requests[1].Params[0] is equal to []byte(`{"C": 1, "D": 2}`)
for _, req := range requests {
if req.Method == "getSomething" {
justProxyThisRequestToAnotherService(req)
} else if req.Method == "getSomethingElse" {
var params []map[string]int
json.Unmarshal(req.Params, ¶ms)
// then do something with params
}
}
Related
Example:
API A:
{
"customer":[
{
"name":"Jane",
"phone":"9999999",
"email":"jane#test.com"
},
{
"name":"John",
"phone":"8888888",
"email":"john#test.com"
},
{
"name":"Joe",
"phone":"7777777",
"email":"Joe#test.com"
}
]
}
Using the JSON extractor, I want to get the names of all the customers
so: Jane, John, Joe
How do I get these values and turn them into an array
[{"name":"Jane", "name":"John", "name":"Joe"}]
And pass it onto the next API?
Note: That it has to be dynamic so API A could show different 2 names or 1 name or more and needs to be adjusted into the array
First of all your [{"name":"Jane", "name":"John", "name":"Joe"}] is not a valid JSON, you can check it yourself:
so I strongly doubt that this is the string you need to generate.
So if you really need to construct this value you can do something like:
Add JSR223 PostProcessor as a child of the request which returns this "customers" data
Put the following code into "Script" area:
def response = new groovy.json.JsonSlurper().parse(prev.getResponseData())
def payload = new StringBuilder()
payload.append('[{')
0.upto(response.customer.size - 1, { index ->
payload.append('"name": "').append(response.customer[index].name).append('"')
if (index != response.customer.size - 1) {
payload.append(',')
}
})
payload.append('}]')
vars.put('payload', payload as String)
Refer the generated value as ${payload} where required
Demo:
More information:
JsonSlurper
Apache Groovy - Parsing and producing JSON
Apache Groovy - Why and How You Should Use It
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 instance:
var commands = [[String: Any]]()
After some calculations, its result is:
[["command": 50022, "homes": [["gateways": [["mac": "845DD74B405E", "services": [["iid": 9, "name": "Some name"]], "aid": 1]], "name": "H1"]]], ["command": 50025, "services": [["mac": "845DD74B405E", "iid": 9, "aid": 1, "new_name": "Some name"]]]]
I want to convert it (commands) to JSON using SwiftyJSON:
let json = JSON(commands)
print(json) // "unknown"
but the result is always unknown.
Then I check the validity of commands to make sure it is JSON-convertable. But I got false with JSONSerialization.isValidJSONObject(commands), which is unexpected!
Do you have any ideas why commands (array of Dictionary) is NOT a valid JSON object?
Thanks
The problem in my commands is at the integer numbers, 50022 and 50025. In my code, they are defined in an enum of UInt32. And when I copied them to a playground to verify, Swift converts it to Int. That is why I always succeed in playground.
Back to my code, Swift 3 expects a number to be an Int in order to convert it to a JSON object successfully. Swift 2 does not have this behavior.
So, after I change my enum define from UInt32 to Int, it just works beautifully!
Thanks everyone.
I'm trying to create a Base64-String in Swift. I have an example of a Base64-encoded string and its array-counterpart. My problem now is, that I don't know how I get an equivalent array to the one which is given in the example.
Because I didn't want to mess around in my XCode-project I did the following in a playground.
given array:
{"WHERE":{"Class":"%3f","Location":"3b"},"ORDER":["Day ASC","Location DESC"]}
given Base64-string:
eyJXSEVSRSI6eyJDbGFzcyI6IiUzZiIsIkxvY2F0aW9uIjoiM2IifSwiT1JERVIiOlsiRGF5IEFTQyIsIkxvY2F0aW9uIERFU0MiXX0=
First I'm decoding the example-string
let str = "eyJXSEVSRSI6eyJDbGFzcyI6IiUzZiIsIkxvY2F0aW9uIjoiM2IifSwiT1JERVIiOlsiRGF5IEFTQyIsIkxvY2F0aW9uIERFU0MiXX0="
let data = NSData(base64EncodedString: str, options: NSDataBase64DecodingOptions(rawValue: 0))
do {
let result = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)
} catch let error {
print(error)
}
//"result" is ["WHERE": ["Class": "%3f", "Location": "3b"], "ORDER": ["Day ASC", "Location DESC"]]
Below I'm trying to reproduce the string from above
var array = [String : AnyObject]()
var arrayPartA = [String : String]()
arrayPartA["Class"] = "%3f"
arrayPartA["Location"] = "3b"
array["ORDER"] = ["Day ASC", "Location DESC"]
array["WHERE"] = arrayPartA
array //The playground says that "array" is ["ORDER": ["Day ASC", "Location DESC"], "WHERE": ["Class": "%3f", "Location": "3b"]]
//"ORDER" and "WHERE" are switched but I don't get them to be at the right position
let utf8str2: NSData = String(array).dataUsingEncoding(NSUTF8StringEncoding)!
let encodedStr = utf8str2.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
//Here "encodedStr" is WyJPUkRFUiI6ICgKICAgICJEYXkgQVNDIiwKICAgICJMb2NhdGlvbiBERVNDIgopLCAiV0hFUkUiOiB7CiAgICBDbGFzcyA9ICIlM2YiOwogICAgTG9jYXRpb24gPSAzYjsKfV0=
//but it should be eyJXSEVSRSI6eyJDbGFzcyI6IiUzZiIsIkxvY2F0aW9uIjoiM2IifSwiT1JERVIiOlsiRGF5IEFTQyIsIkxvY2F0aW9uIERFU0MiXX0=
I would be glad if someone could explain to me what I'm doing wrong and how I can reproduce the given Base64-string.
Since I'm new to this website I apologize in advance for wrong layout or other possible conventions I don't know.
Could you try this please? Is this what you wanted to do? It should convert a Dictionary to base64 String
func jsonToBaseString (yourJSON: [String: String]) -> String? {
do {
let jsonData = try JSONSerialization.data(withJSONObject: yourJSON, options: JSONSerialization.WritingOptions.prettyPrinted)
return
jsonData.base64EncodedString(options: .endLineWithCarriageReturn)
} catch {
return nil
}
}
Dictionary is Swifts JSON representation...
Two important things to understand:
What you are calling an array is not an array, it's a JSON dictionary (containing an array for the ORDER key).
Be careful not to confuse the syntax of arrays and dictionaries between Swift and JSON.
In Swift, an array: [0, 1], a dictionary: ["a":0, "b":1].
In JSON, an array: [0, 1], a dictionary: {"a":0, "b":1}.
A Swift dictionary is an unordered collection. There's no "position" for key-value pairs.
You'll need to change several things:
Your input string (not serialized) is not an array, but a JSON object.
Try constructing your string with a proper JSON library, such as SwiftyJSON.
String(array) is not enough to consistently convert your objects to strings. You should use a JSON serializer (such as SwiftyJSON json.rawString()).
let follow recommendation to use some json serialization, but take in account that
{
"alfa": 1,
"beta": true
}
and
{"beta":true,"alfa":1}
represents in JSON notation the same object even though their string representation ( doesn't matter if base64 encoded or not ) are different.