How to get just one attribute value out of json string - json

i am pretty new to python and i tried some things but can't seem to find the solution for this.
I am making a get request to a ldap local server and the response is a list, i don't know if this is a list of lists or just a list.
[
"cn=Philip J. Fry,ou=people,dc=planetexpress,dc=com",
"cn=Turanga Leela,ou=people,dc=planetexpress,dc=com",
"cn=Bender Bending Rodr\u00edguez,ou=people,dc=planetexpress,dc=com"
]
I want to return a json with only the "cn" values.
Like this:
[
"Philip",
"Turanga",
"Bender"
]
Thanks for the help

I would convert the strings into dictionaries:
def ldap_to_dict(string):
d = {}
for pair in string.split(","):
key, val = pair.split("=")
if key in d: # handle multiple value case
if isinstance(d[key], list):
d[key].append(val)
else:
d[key] = [d[key], val]
else:
d[key] = val
return d
names = [ldap_to_dict(ldap_string)["cn"] for ldap_string in original_list]
Aftermath:
>>> names
['Philip J. Fry', 'Turanga Leela', 'Bender Bending Rodríguez']

Thanks guys for the quick responses.
I manage to do it like this:
list1 = []
list2 = []
list3 = []
#app.route('/users', methods=['GET'])
def list_users():
string = (ldap.get_group_members('ship_crew'))
for user in string:
list1.append(user.split(",")[0])
a = list1
for user in a:
list2.append(user.split("=")[1])
b = list2
for user in b:
list3.append(user.split(" ")[0])
return jsonify(list3)
Output:
['Philip', 'Turanga', 'Bender']
But now when i'am trying to return it as json with this command:
curl -X GET -H "Content-type: application/json charset=UTF-8" -H "Accept: application/json" http://localhost:5000/users
I get:
TypeError: a bytes-like object is required, not 'str'
Even if i json.dump my list3 and get:
["Philip", "Turanga", "Bender"]
I got the same error.
I'am getting my string from a ldap.
What's the problem here?
Thanks

Related

Replace Json string in Ruby

First, I have a json:
json = "{\"string_1\": \"{{string_1_value}}\", \"number_1\": \"{{number_1_value}}\"}"
And this hash:
hash = {
"{{string_1_value}}" => "test" //string
"{{number_1_value}}" => 2 //integer
}
What I'd like to do is to replace json with this hash and generate below json.
"{\"string_1\": \"test\", \"number_1\": 2}"
When I do this by String#gsub, I got an Error.
hash.map {|k, v| json.gsub!(k, v)}
=> TypeError (no implicit conversion of Integer into String)
I don't want 2 to be string, i.e.)
"{"string_1": "test", "number_1": "2"}"
Do you have any idea?
Thank you in advance.
First, in ruby comments are marked by # not //. And remember about the comma in hash.
gsub is not the fastest way to replace things, it's better to convert json to regular hash and then convert it again to json.
require 'json'
json = "{\"string_1\": \"{{string_1_value}}\", \"number_1\": \"{{number_1_value}}\"}"
hash = {
"{{string_1_value}}" => "test", #string
"{{number_1_value}}" => 2 #integer
}
# First you should parse your json and change it to hash:
parsed_json = JSON.parse(json)
# Then create keys array
keys = parsed_json.keys
# Create new empty hash
new_hash = {}
# And now fill new hash with keys and values
# (take a look at to_s, it converts values to a String)
hash.each.with_index do |(_k, v), i|
new_hash[keys[i]] = v.to_s
end
# Convert to json at the end
new_hash.to_json
# => "{\"string_1\":\"test\",\"number_1\":\"2\"}"
You can use the Regexp,Hash version of String#gsub to just substitute the patterns with the desired values as follows:
require 'json'
json_string = "{\"string_1\": \"{{string_1_value}}\", \"number_1\": \"{{number_1_value}}\"}"
original_hash= {
"{{string_1_value}}" => "test", #string
"{{number_1_value}}" => 2 #integer
}
#Convert JSON to hash and invert the key value pairs
parsed_json = JSON.parse(json_string).invert
#=>{"{{string_1_value}}"=>"string_1", "{{number_1_value}}"=>"number_1"}
# Convert the hash to JSON and substitute the patterns
original_hash.to_json.gsub(/\{\{.+?\}\}/, parsed_json)
#=> "{\"string_1\":\"test\",\"number_1\":2}"

How to parse a string to key value pair using regex?

What is the best way to parse the string into key value pair using regex?
Sample input:
application="fre" category="MessagingEvent" messagingEventType="MessageReceived"
Expected output:
application "fre"
Category "MessagingEvent"
messagingEventType "MessageReceived"
We already tried the following regex and its working.
application=(?<application>(...)*) *category=(?<Category>\S*) *messagingEventType=(?<messagingEventType>\S*)
But we want a generic regex which will parse the sample input to the expected output as key value pair?
Any idea or solution will be helpful.
input = 'application="fre" category="MessagingEvent" messagingEventType="MessageReceived"'
puts input.
scan(/(\w+)="([^"]+)"/). # scan for KV-pairs
map{ |k, v| %Q|#{k.ljust(30,' ')}"#{v}"| }. # adjust as you requested
join($/) # join with platform-dependent line delimiters
#⇒ application "fre"
# category "MessagingEvent"
# messagingEventType "MessageReceived"
Instead of using regex, it can be done by spliting and storing the string in hash like below:
input = 'application="fre" category="MessagingEvent" messagingEventType="MessageReceived"'
res = {}
input.split.each { |str| a,b = str.split('='); res[a] = b}
puts res
==> {"application"=>"\"fre\"", "category"=>"\"MessagingEvent\"", "messagingEventType"=>"\"MessageReceived\""}

JSON no longer parsable after being sent through TCP in Ruby

I've created a basic client and server that pass a string, which I've changed to JSON instead. But the JSON string is only parsable before it gets sent through TCP. After it's sent, the string version is identical (after a chomp), but on the server side it no longer processes the JSON correctly. Here is some of my code (with other bits trimmed)
Some of the client code
require 'json'
require 'socket'
foo = {'a' => 1, 'b' => 2, 'c' => 3}
puts foo.to_s + "......."
foo.to_json
puts foo['b'] # => outputs the correct '2' answer
client = TCPSocket.open('localhost', 2000)
client.puts json
client.close;
Some of the server code
require 'socket'
require 'json'
server = TCPServer.open(2000)
while true
client = server.accept # Accept client
response = client.gets
print response
response = response.chomp
response.to_json
puts response['b'] # => outputs 'b'
end
The output 'b' should be '2' instead. How do I fix this?
Thanks
In your server you wrote response.to_json. This turns a string to JSON, then throws it away. And I don't like the .chomp, either.
Try
response = client.gets
hash = JSON.parse(response)
Now hash is a Ruby Hash object with your data in it, and hash['b'] should work correctly.
The problem is that .to_json does not parse JSON inside a string and replace itself with the result. It is used to convert the string into a format that is an acceptable JSON value.
require 'json'
string = "abc"
puts string
puts string.to_json
This will output:
abc
"abc"
The method is added to the String class by the JSON generator and it uses it internally to generate the JSON document.
But why does your response['b'] return "b"?
Because Ruby strings have a method called [] that can be used to:
Return a substring: "abc"[0,2] => "ab"
Return a single character from index: "abc"[1] => "b"
Return a substring if the string contains it: "abc"["bc"] => "bc", "abc"["fg"] => nil
Return a regexp match: "abc"[/^a([a-z])c/, 1] => "b"
and possibly some other ways I can't think of right now.
So this happens because your response is a string that has the character "b" in it:
response = "something with a b"
puts response["b"]
# outputs b
puts response["x"]
# outputs a blank line because response does not contain "x".
Instead of .to_json your code has to call JSON.parse or JSON.load:
data = JSON.parse(response)
puts data['b']

How Do I Consume an Array of JSON Objects using Plumber in R

I have been experimenting with Plumber in R recently, and am having success when I pass the following data using a POST request;
{"Gender": "F", "State": "AZ"}
This allows me to write a function like the following to return the data.
#* #post /score
score <- function(Gender, State){
data <- list(
Gender = as.factor(Gender)
, State = as.factor(State))
return(data)
}
However, when I try to POST an array of JSON objects, I can't seem to access the data through the function
[{"Gender":"F","State":"AZ"},{"Gender":"F","State":"NY"},{"Gender":"M","State":"DC"}]
I get the following error
{
"error": [
"500 - Internal server error"
],
"message": [
"Error in is.factor(x): argument \"Gender\" is missing, with no default\n"
]
}
Does anyone have an idea of how Plumber parses JSON? I'm not sure how to access and assign the fields to vectors to score the data.
Thanks in advance
I see two possible solutions here. The first would be a command line based approach which I assume you were attempting. I tested this on a Windows OS and used column based data.frame encoding which I prefer due to shorter JSON string lengths. Make sure to escape quotation marks correctly to avoid 'argument "..." is missing, with no default' errors:
curl -H "Content-Type: application/json" --data "{\"Gender\":[\"F\",\"F\",\"M\"],\"State\":[\"AZ\",\"NY\",\"DC\"]}" http://localhost:8000/score
# [["F","F","M"],["AZ","NY","DC"]]
The second approach is R native and has the advantage of having everything in one place:
library(jsonlite)
library(httr)
## sample data
lst = list(
Gender = c("F", "F", "M")
, State = c("AZ", "NY", "DC")
)
## jsonify
jsn = lapply(
lst
, toJSON
)
## query
request = POST(
url = "http://localhost:8000/score?"
, query = jsn # values must be length 1
)
response = content(
request
, as = "text"
, encoding = "UTF-8"
)
fromJSON(
response
)
# [,1]
# [1,] "[\"F\",\"F\",\"M\"]"
# [2,] "[\"AZ\",\"NY\",\"DC\"]"
Be aware that httr::POST() expects a list of length-1 values as query input, so the array data should be jsonified beforehand. If you want to avoid the additional package imports altogether, some system(), sprintf(), etc. magic should do the trick.
Finally, here is my plumber endpoint (living in R/plumber.R and condensed a little bit):
#* #post /score
score = function(Gender, State){
lapply(
list(Gender, State)
, as.factor
)
}
and code to fire up the API:
pr = plumber::plumb("R/plumber.R")
pr$run(port = 8000)

Print a value of a key from json

I am trying to parse a json file and extract the value of a key from it, and pass it to another post request. However, I am not able to extract they value, when I try, it prints the key itself instead of value
PFB the json file
{
"data":{
"isActivated":true,
"userDetails":{
"userId":"52321713-add8-4455-9e0c-426eab923338",
"oktaId":"00ub24c5bs6awQyBD0h7",
"contactId":"7234294092390",
"oktaSessionToken":"20111UqAZ9-E1YPlNcXBLRCu_ZHHzBCH2q_j01yiIkPyRp5-0E7HAQQ",
"oktaSessionId":"102a9q79TrqRWek9vHEPkP3yQ",
"apiToken":"f5c95fd8-efc4-497e-8128-51a014de3a9a",
"firstName":"Judy",
"lastName":"Test1",
"middleName":null,
"email":"abc#mailinator.com",
"isEmployee":true,
"pushNotificationStatus":true
},
"companyDetails":{
"profileScreenBackgroundColor":"13253D",
"companyColor":"7ED321",
"companyName":"Mobile App Demo",
"companyLogo":"http://",
"isSSO":false
}
}
}
PFB the hash file:
{"data"=>{"isActivated"=>true, "userDetails"=>
{"userId"=>"52321713-add8-4455-9e0c-426eab923338",
"oktaId"=>"00ub24c5bs6awQyBD0h7", "contactId"=>"0033300001tZ8k5AAC",
"oktaSessionToken"=>"201112Ncbw364pHojkD4UlzGb1knz9UTZPIy2LFDn9Tgy_FmgEpZmmU",
"oktaSessionId"=>"102Kd-c2yEeSnmwr3YKX8qeyg",
"apiToken"=>"f8f070e2-e51b-4d69-8b1a-b7b63d25e781",
"firstName"=>"Judy", "lastName"=>"Test1",
"middleName"=>nil,
"email"=>"judy.test1#mailinator.com",
"isEmployee"=>true,
"pushNotificationStatus"=>true},
"companyDetails"=>{"profileScreenBackgroundColor"=>"13253D", "companyColor"=>"7ED321",
"companyName"=>"Mobile App Demo", "companyLogo"=>"https:",
"isSSO"=>false}}}
The code below:
I had tried almost all means, not sure what am i missing.
apitoken = RestClient.post("https://", {'email'=>arg,'password'=>'abcs','deviceUUId'=>'udid', 'deviceTypeId'=>1}.to_json, { "Content-Type" => 'application/json','buildNumber' => '000','deviceTypeId'=>'9'})
puts apitoken
puts "**************"
puts apitoken["apiToken"]
logindetails = JSON.parse(apitoken)
tada = JSON.parse(logindetails)['data']['apitoken']
puts tada
puts logindetails
result = logindetails["data"]["apiToken"]
puts result
puts "**************"
logindetails.each do |logindetail|
puts logindetail
puts logindetail["apiToken]
puts "**************"
end
result = logindetails['apiToken']
puts result
end
The output I get is apiToken instead of the value of it. Any help is greatly appreciated.
The token is under data userDetails apiToken:
json['data']['userDetails']['apiToken'] #=> f5c95fd8-efc4-497e-8128-51a014de3a9a