Why Python JSON output always added with escape string? - python

the code
import json
jsonData = {
'url' : 'test/file.jpg'
}
arrayData = json.dumps(jsonData)
# load the json to a string
resp = json.loads(arrayData)
resp['url'] = resp['url'].replace(r'/',r'\/')
print('without JSON output:',resp['url'])
jsonDataNew = [
{'url' : str(resp['url'])}
]
json_data = json.dumps(jsonDataNew)
json_data = json.loads(json_data)
print('with JSON output')
print(json_data)
the output
without JSON output: test\/file.jpg
with JSON output
[{'url': 'test\\/file.jpg'}]
the desired output would be
with JSON output
[{'url': 'test\/file.jpg'}]
no matter how, im not able to remove the escape in the JSON output, even converted into JSON file. is this something unavoidable in Python?

This is because it uses backslash to escape backslash. In that sense, the double backslash you saw is actually interpreted as a single character.
For an example,
>>> a = 'test\\'
>>> a
'test\\'
>>> print(a)
test\
You can read up for more on repr
On the other hand, if what you want to do is to escape the forward slashes. Perhaps the easier and cleaner solution is to use ujson.
import ujson
jsonData = {
'url' : 'test/file.jpg'
}
json_data = ujson.dumps(jsonData, escape_forward_slashes=True)
print(json_data)
The output will be :
{"url":"test\/file.jpg"}

Related

how to prevent python json.loads() to decoding characters unnecessarily

I have a file that has:
{
"name": "HOSTNAME_HTTP",
"description": "Custom hostname for http service route. Leave blank for default hostname, e.g.: \u003capplication-name\u003e-\u003cproject\u003e.\u003cdefault-domain-suffix\u003e"
}
when I open the file using:
with open('data.txt', 'r') as file:
data = file.read()
I pass this to json.loads and the content in data is replaced with:
<application>...</application>
How can I prevent python json.loads from messing with the encoding in the content?
You could use a workaround like this to escape the unicode sequences:
>>> obj = json.loads(data.replace('\\', '\\\\'))
>>> obj
{'name': 'HOSTNAME_HTTP',
'description': 'Custom hostname for http service route. Leave blank for default hostname, e.g.: \\u003capplication-name\\u003e-\\u003cproject\\u003e.\\u003cdefault-domain-suffix\\u003e'}
And then when you're done modifying:
>>> print(json.dumps(obj).replace('\\\\', '\\'))
{"name": "HOSTNAME_HTTP", "description": "Custom hostname for http service route. Leave blank for default hostname, e.g.: \u003capplication-name\u003e-\u003cproject\u003e.\u003cdefault-domain-suffix\u003e"}
If you expect other backslashes in the file, it would be safer to use regular expressions:
import re
from_pattern = re.compile(r'(\\u[0-9a-fA-F]{4})')
to_pattern = re.compile(r'\\(\\u[0-9a-fA-F]{4})')
def from_json_escaped(path):
with open(path, 'r') as f:
return json.loads(from_pattern.sub(r'\\\1', f.read()))
def to_json_escaped(path, obj):
with open(path, 'w') as f:
f.write(to_pattern.sub(r'\1', json.dumps(obj)))
I found a solution:
import json
from json.decoder import JSONDecoder
with open('data.txt', 'r') as file:
data = file.read()
data_without_dump = '{"data":\"' + data + '\"}'
datum_dump = json.dumps(data)
datum = '{"data": ' + datum_dump + '}'
datum_load = json.loads(datum)
datum_load_without_dump = json.loads(data_without_dump)
print(datum_dump)
print(datum)
print(datum_load["data"])
print(datum_load_without_dump["data"])
print(type(datum_dump), type(datum), type(datum_load))
Output:
"\\u003capplication\\u003e.....\\u003c/application\\u003e"
{"data": "\\u003capplication\\u003e.....\\u003c/application\\u003e"}
\u003capplication\u003e.....\u003c/application\u003e
<application>.....</application>
<class 'str'> <class 'str'> <class 'dict'>
My reasoning:
json.loads : Deserialize a str or unicode instance containing a JSON document to a Python object.
json.dumps : Serialize obj to a JSON formatted str.
So, using them in cascading gets the desired result.

Json dump for key, pair in Python

I have below file which is the result of a json dump.
"fdd6a102-359c-4527-8469-4ef01a9c0076": "[\n {\n \"resource_status\": \"CREATE_COMPLETE\", \n \"resource_name\": \"i4_instance_internal_port\", \n \"resource_type\": \"OS::Neutron::Port\", \n \"physical_resource_id\": \"5db1d412-9a43-45c7-b72d-0dbe4eb16497\", \n \"updated_time\": \"2017-07-14T09:00:44\"\n }, \n {\n \"resource_status\": \"CREATE_COMPLETE\", \n \"resource_name\": \"i3_instance\", \n \"resource_type\": \"OS::Nova::Server\", \n \"physical_resource_id\": \"50375d90-5b57-412e-afe3-fdddefbd2f41\", \n \"updated_time\": \"2017-07-14T09:00:44\"\n }, \n {\n \"resource_status\": \"CREATE_COMPLETE\", \n \"resource_name\": \"i3_v1_instance_volume\", \n \"resource_type\": \"OS::Cinder::Volume\", \n \"physical_resource_id\": \"6750dc3d-e682-4a0c-a177-83a7252822fb\", \n \"updated_time\": \"2017-07-14T09:00:44\"\n }\n]\n"
This file is messed up I think. It is not in the right format. I researched on how to dump in json
def pp_another_json(myDict):
import io
try:
to_unicode = unicode
except NameError:
to_unicode = str
# Write JSON file
with io.open('data.json', 'w', encoding='utf8') as outfile:
str_ = json.dumps(myDict,
indent=4, sort_keys=True,
ensure_ascii=False)
outfile.write(to_unicode(str_))
class getstackList():
def getStackID(self):
stacks = get_objects('stacks')
myDict = {}
for stack in stacks:
try:
myDict[stack.id] = subprocess.check_output(["openstack", "stack", "resource", "list", stack.id, "-f", "json"])
pp_another_json(myDict)
except subprocess.CalledProcessError as e:
print("Error")
The output of openstack stack resource list -f json comes in below format
[
{
"resource_status": "CREATE_COMPLETE",
"resource_name": "i4_instance_internal_port",
"resource_type": "OS::Neutron::Port",
"physical_resource_id": "5db1d412-9a43-45c7-b72d-0dbe4eb16497",
"updated_time": "2017-07-14T09:00:44"
},
{
"resource_status": "CREATE_COMPLETE",
"resource_name": "i3_instance",
"resource_type": "OS::Nova::Server",
"physical_resource_id": "50375d90-5b57-412e-afe3-fdddefbd2f41",
"updated_time": "2017-07-14T09:00:44"
},
]
Now my problems
The json dump file doesn't really look like json to me. How can I get it to be in proper format
The json dump file is a big one. so I have key as the ID and the value is the list inside which there is another dictionary.(I think so) How do I fetch data in such scenario?
I need to check for example if 'resource_type' is OS::Cinder::Volume, how will I get it or else if I need to get the value of resource_type, how will I get it?
It will be helpful if someone can explain me my json file. Or if not, please direct me to the links that could help me understand nested dictionaries
Edited : To fetch the value I did below and is giving me
ValueError: too many values to unpack
with open('data.json') as data_file:
data_loaded = json.load(data_file)
for key, value in data_loaded:
print(data_loaded[key][0]['resource_status'])
data.json is below
Your JSON dump can be viewed as a simple dictionary in python. So for your first part you can use the following :
import json
#Assuming 'mydict' contains the json dump
with open('out.json', 'w') as outfile:
json.dump(mydict, outfile)
Now coming to the second part, suppose for the first element (fdd6a102-359c-4527-8469-4ef01a9c0076") in your example you need to access the 'resource-status' key of the first element in the list, you simply need to use the following:
myjson["fdd6a102-359c-4527-8469-4ef01a9c0076"][0]['resource-status']
More information can be found here.
For your final part, you view this answer on nested JSON.

Zero size length on json object in Python

I'm not sure why this happen, there are zero length in my json file.
0
I t supposedly to be like this,
1000
I'm afraid the comma thing after each json object cause this issue. (My current json format)
{ A:"A"},{ B:"B"),...
The correct way is like this
{ A:"A"} { B:"B"),...
So how I can calculate all the length without removing the comma?
My code
import json
githubusers_data_path = 'githubusers.json'
githubusers_data = []
githubusers_file = open(githubusers_data_path, "r")
for line in githubusers_file:
try:
data = json.loads(line)
githubusers_data.append(data)
except:
continue
print len(githubusers_data)
Sample
{
"login": "datomnurdin"
}, {
"login": "ejamesc"
},...
I think you're getting an exception that you're suppressing with try-except, because of the commas.
One solution would be to convert your file to a string first, stick a '[' and ']' around the string to convert it into a valid json format, then use json.loads to convert the string.
import json
githubusers_data_path = 'githubusers.json'
githubusers_file = open(githubusers_data_path, "r")
githubusers_string = ''.join(line for line in githubusers_file)
githubusers_string = '[{}]'.format(githubusers_string)
githubusers_data = json.loads(githubusers_string)
print len(githubusers_data)
githubusers_file.close()
there is an exception in your code:
import json
githubusers_data_path = 'githubusers.json'
githubusers_data = []
githubusers_file = open(githubusers_data_path, "r")
for line in githubusers_file:
try:
data = json.load(githubusers_file) # exception from here
githubusers_data.append(data)
except Exception, e:
print e
print len(githubusers_data) # so githubusers_data is always []
Mixing iteration and read methods would lose data

Parsing formatted JSON with Python

I want to parse JSON. Its ok if I write JSON in one line
json_input = '{ "rate_of_climbing": 18.4, "speed_factor": 520}'
But if I have JSON formated then parser does not work:
json_input = '{
"rate_of_climbing": 18.4,
"speed_factor": 520
}'
How can I get JSON to read for formatted string?
My full code:
import json
json_input = '{
"rate_of_climbing": 18.4,
"speed_factor": 520
}'
try:
decoded = json.loads(json_input)
print json.dumps(decoded, sort_keys=True, indent=4)
print "JSON parsing example: ", decoded['rate_of_climbing']
print "Complex JSON parsing example: ", decoded['speed_factor']
except (ValueError, KeyError, TypeError):
print "JSON format error"
Use '''triple-quoted string literals''' (or """triple-quoted string literals""") if the string contains newlines.
json_input = '''{
"rate_of_climbing": 18.4,
"speed_factor": 520
}'''
I think you can store these json data info a file;
then read all:
json_data = ''.join([line.strip() for line in open('path to json file')])
then,
_data = json.loads(json_data)
json.dumps(_data)

TypeError: expected string or buffer in Google App Engine's Python

I want to show the content of an object using the following code:
def get(self):
url="https://www.googleapis.com/language/translate/v2?key=MY-BILLING-KEY&q=hello&source=en&target=ja"
data = urllib2.urlopen(url)
parse_data = json.load(data)
parsed_data = parse_data['data']['translations']
// This command is ok
self.response.out.write("<br>")
// This command shows above error
self.response.out.write(str(json.loads(parsed_data[u'data'][u'translations'][u'translatedText'])))
But the error
TypeError: expected string or buffer
appears as a result of the line:
self.response.out.write(str(json.loads(parsed_data[u'data'][u'translations'][u'translatedText'])))
or
self.response.out.write(json.loads(parsed_data[u'data'][u'translations'][u'translatedText']))
UPDATE (fix):
I needed to convert from string to JSON object:
# Convert to String
parsed_data = json.dumps(parsed_data)
# Convert to JSON Object
json_object = json.loads(parsed_data)
# Parse JSON Object
translatedObject = json_object[0]['translatedText']
# Output to page, by using HTML
self.response.out.write(translatedObject)
parse_data = json.load(data)
parsed_data = parse_data['data']['translations']
Those lines already did the json.load, and extracted 'data' and 'translations'. Then instead of:
self.response.out.write(str(
json.loads(parsed_data)[u'data'][u'translations'][u'translatedText']))
you should:
self.response.out.write(str(
parsed_data[u'translatedText']))
All I need, is convert from String to JSON object, as the following code :
# Convert to String
parsed_data = json.dumps(parsed_data)
# Convert to JSON Object
json_object = json.loads(parsed_data)
# Parse JSON Object
translatedObject = json_object[0]['translatedText']
# Output to page, by using HTML
self.response.out.write(translatedObject)
The urllib2.urlopen function return a file-like object, not a string. You should read the response first.
url = "http://www.example.com/data"
f = urllib2.urlopen(url)
data = f.read()
print json.loads(data)

Categories