Json response in Go(Gin) without escape characters - go

I have recently started working on Go APIs using GIN. My API is getting the data from DB with two columns where one column contains integer and other contains a json string.
The json string is dynamic and hence i cant use struct for that.
I am using map[string]interface{} to parse the json and modify it and then parse it back to json using json.Marshal. Now i am returning this json string as a response but getting escape characters. Have done some search regarding that, but didnt find any solution yet.
Here is the part of code that i am using
var interface_obj map[string]interface{}
json.Unmarshal([]byte(grants.Data), &interface_obj)
grants_map := interface_obj["role_grants"].(map[string]interface{})
jsonString, err := json.Marshal(grants_map)
jsonBody := string(jsonString)
After this, I am returning this JSON as response in GIN framework like this
c.JSON(http.StatusCreated, gin.H{"message": "Json retrieved successfully", "data": jsonBody})
But the output i am getting is
{
"data": "[{\"action\":\"read\",\"resource\":\"project\"},{\"action\":\"all\",\"resource\":\"users\"},{\"action\":\"all\",\"resource\":\"roles\"},{\"action\":\"all\",\"resource\":\"project-settings\"},{\"action\":\"create\",\"resource\":\"single-entity-screening\"},{\"action\":\"read\",\"resource\":\"single-entity-screening\"},{\"action\":\"create\",\"resource\":\"multi-batch-screening\"},{\"action\":\"read\",\"resource\":\"multi-batch-screening\"},{\"action\":\"read\",\"resource\":\"workspace\"},{\"action\":\"allocate\",\"resource\":\"workspace\"},{\"action\":\"update\",\"resource\":\"workspace\"},{\"action\":\"read\",\"resource\":\"case\"},{\"action\":\"allocate\",\"resource\":\"case\"},{\"action\":\"review\",\"resource\":\"case\"},{\"action\":\"update\",\"resource\":\"case\"},{\"action\":\"read\",\"resource\":\"report\"},{\"action\":\"read\",\"resource\":\"audit-trail\"},{\"action\":\"read\",\"resource\":\"delivery\"}]",
"message": "Grants retrieved successfully"
}
I printed it on my console and it looked fine there, but causing this issue on response.
Is there any way to resolve this using some standard way? Please guide
Thanks

You don't need to do json.Marshal(grants_map), just pass the value directly to gin.H and let c.JSON do the encoding, i.e.
gin.H{... "data": grants_map}
And in cases where you truly have raw JSON data at hand that you want to send as part of other not-yet-JSON data, you can wrap it into json.RawMessage to avoid the "double-encoding", i.e.
gin.H{... "data": json.RawMessage(jsonBody)}

Related

Trying to get a JSONPath array of all leaves on json object

New to Go. My first project is to compare a NodeJS proxy and a Go proxy for account number tokenization. I have been doing NodeJS for a few years and am very comfortable with it. My proxies will not know the format of any request or response from the target servers. But it does have configurations coming from Redis/MongoDB that is similar to JSONPath expression. These configurations can change things like the target server/path, query parameters, headers, request body and response body.
For NodeJS, I am using deepdash's paths function to get an array of all the leaves in a JSON object in JSONPath format. I am using this array and RegEx to find my matching paths that I need to process from any request or response body. So far, it looks like I will be using gjson for my JSONPath needs, but it does not have anything for the paths command I was using in deepdash.
Will I need to create a recursive function to build this JSONPath array myself, or does anyone know of a library that will produce something similar?
for example:
{
"response": {
"results": [
{
"acctNum": 1234,
"someData": "something"
},
{
"acctNum": 5678,
"someData": "something2"
}
]
}
}
I will get an array back in the format:
[
"response.results[0].acctNum",
"response.results[0].someData",
"response.results[1].acctNum",
"response.results[1].someData"
]
and I can then use my filter of response.results[*].acctNum which translates to response\.results\[.*\]\.acctNum in Regex to get my acctNum fields.
From this filtered array, I should be able to use gjson to get the actual value, process it and then set the new value (I am using lodash in NodeJS)
There are a number of JSONPath implementations in GoLang. And I cannot really give a recommendation in this respect.
However, I think all you need is this basic path: $..*
It should return in pretty much any implementation that is able to return pathes instead of values:
[
"$['response']",
"$['response']['results']",
"$['response']['results'][0]",
"$['response']['results'][1]",
"$['response']['results'][0]['acctNum']",
"$['response']['results'][0]['someData']",
"$['response']['results'][1]['acctNum']",
"$['response']['results'][1]['someData']"
]
If I understand correctly this should still work using your approach filtering using RegEx.
Go SONPath implementations:
http://github.com-PaesslerAG-jsonpath
http://github.com-bhmj-jsonslice
http://github.com-ohler55-ojg
http://github.com-oliveagle-jsonpath
http://github.com-spyzhov-ajson
http://github.com-vmware-labs-yaml-jsonpath

Accessing fields in a GO structure

I am new to the Golang world and trying to parse a json response returned by AWS API.
I've tried parsing the result by dot notation and seem to get success in the higher levels. Below is what my experimentation resulted to.
For brevity I excluded other fields
Test 1
fmt.Println(result)
returns
{
DBClusterSnapshots: [{
Status: "available"
}]
}
Test 2
fmt.Println(result.DBClusterSnapshots[0])
returns
{
Status: "available"
}
Test 3
fmt.Println(result.DBClusterSnapshots[0].Status)
returns what seem to be a reference to an object
0xc0001e74c8
Given the last example (Test 3) how do I parse it properly to get the value of Status which is "available"
As pointed out by #mkopriva
Status is a pointer and therefore need to be dereference when intending to extract the string.
so to achieve extracting the value of status we can dereference it like this.
s := *result.DBClusterSnapshots[0].Status
fmt.Println(s)

go properly handling slices and strings

I am using goRequest http://parnurzeal.github.io/gorequest/ to make some HTTP requests against a server process I need to talk to. The authentication process works like this;
send in a GET request with an authentication header set. No problem there, but I need to grab a header from the response and use a returned value to reauthenticate each following request.
The retuned HTTP header looks like this.
Response headers
map[Location:[900767244] Content-Type:[application/xml] Date:[Fri, 18 Sep 2015 18:19:41 GMT] Server:[Apache] X-Frame-Options:[SAMEORIGIN] Set-Cookie:[JSESSIONID=D5C976F5646365FF030DBAD770DA774C; Path=/; Secure; HttpOnly]]
I need to get that location value as it's my session token going forward. If I grap it like this:
session, ok := response.Header["Location"]
if !ok {
fmt.Println("Did not receive a location header.")
}
fmt.Println("Session: ", session)
I can get it, but it's a slice and NOT a string. How can I get that value as a string so I can pop it back into my request headers going forward? As you can see in the following error:
./login.go:133: cannot use session (type []string) as type string in argument to logoutRequest.Delete
Thanks a lot!
Craig
If you want one value, use the Header's Get method
location := response.Header.Get("Location")
This also canonicalizes the header name for you, so that you still get a value even when using slightly different capitalization.
You only need to index an http.Header value directly when you need to get more than than the first possible value. If you want all values with a canonicalized header name, you can use textproto.CanonicalMIMEHeaderKey
vals := response.Header[textproto.CanonicalMIMEHeaderKey(header)]
The headers have location as an array, you just need to pass Location[0] to that method rather than simply Location because it is a slice. That being said, indexing into the array without checking the bounds is unsafe so you should probably do;
if len(Location) == 1 {
logoutRequest(Location[0])
} else {
// error state
}
One last thing to provide you guidance in the future. You can tell that the response headers object has a type more like this; map[string][]string (in reality that maybe []interface{} but I'm not certain from the output) by seeing that each item inside the outer brackets [] has it's values contained within another set of brackets, meaning it is an array that could contain 0 or more values.

how to send regex to server side in meteor

In my application, I'm building a query object some thing like below
Object {pointType: /analog/i, _id: Object}
I tried to store it in session variable,
Session.set("currentPointsQueryObject",queryObj);
Then on click event I'm getting this object
var res= Session.get("currentPointsQueryObject");
console.log(res);
but here I'm getting like below
Object {pointType: Object, _id: Object}
Meanwhile, I sent group_id to the server
by geting it from session variable like
var group_id=Session.get("currentGroupId");
which is working fine(it is displaying id in server log)
Then, I've tried storing it in global variable, which returning as expected
like below on click event
Object {pointType: /analog/i, _id: Object}
but when I sent it to server side method (Immediate line after console.log() )
Meteor.call("updateGroupPoints",res,function(err,data){
console.log("updated points");
console.log(data);
});
when I log res in server console, it is showing
{ pointType: {}, _id: { '$nin': [] } }
Althoug I have something in pointType, It is not passed to the server.
Anyone had idea, Is this the thing related storing?
You cannot directly serialize RegExp to EJSON, but you can:
var regexp = /^[0-9]+$/;
var serialized = regexp.source;
Send serialized and then deserialize:
new RegExp(serialized)
Take a look at : Meteor: Save RegExp Object to Session
/analog/i is a regular expression, right? Values stored in Session and values sent to methods must be part of EJSON values. Regular expression aren't.
There's a handy way to teach EJSON how to serialize/parse Regular Expressions (RegExp) as of 2015 documented in this SO question:
How to extend EJSON to serialize RegEx for Meteor Client-Server interactions?
Basically, we can extend the RegExp object class and use EJSON.addType to teach the serialization to both client and server. Hope this helps someone out there in the Universe. :)
Simply stringify your RegExp via .toString(), send it to the server and then parse it back to RegExp.

Trying to extract key value from parsed JSON in ruby

I’m trying to parse some JSON from the twitter API and extract the value of a key (“media_url”), which is a sub-key of the key (“entities”)
so far I have:
url = 'https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&screen_name=print_broadcast&count=1'
response = RestClient.get(url)
data=response.body
result = JSON.parse(data)
How would I extract a key value from the parsed JSON?
I’ve tried
result[“entities”]
etc, but I get en error when trying to convert a string to integer... the result of my parsed JSON is an array - shouldn't this be a hash?
Sorry for the dumb questions.
Any help would be appreciated.
The JSON output is actually a list. Granted, it only has one element, but it's still a list.
First get result[0], then you can access ['entries'].

Resources