Variable changes its format on printing - python

I am trying to store a variable with Key Value data in a file using Python, but when I try printing it, it comes up in a different format.
I want the result to be printed like this-
data={"name":'name',"description": "This is my offering","icon":"/csa/api/blobstore/Magic_RGB_blue_NT.png?tag=library","version": "1.0.0",
"design": {
"#self": "#self"
}
}
This is the output I get while printing the data-
{'icon': '/csa/api/blobstore/Magic_RGB_blue_NT.png?tag=library', 'design': {'#self': '#self'}, 'name': 'name', 'version': '1.0.0', 'description': 'This is my offering'}

You haven't stated what is important to you when printing, nor how you are currently attempting to print.
There is no formatting within a dictionary. Any formatting in your code is merely to make the code look human readable and is not actually stored within your data dictionary (only formatting within each string element is retained, ie, between a pair of quotes).
If it is merely the format (multiple lines and indents) that you are concerned about, the easiest way to resolve that is to use either the Pretty Print module or the JSON module - either should do the job, depending on your preferences for how you want the data to look and how much control you want to have over the printed output format. In particular, the JSON output occupies more vertical screen space, but some people may think that it is marginally more human readable.
PrettyPrint pprint:
import pprint
data={"name":'name',"description": "This is my offering","icon":"/csa/api/blobstore/Magic_RGB_blue_NT.png?tag=library","version": "1.0.0","design": {"#self": "#self"}}
pp = pprint.PrettyPrinter(indent=4)
pp.pprint(data)
>>>
{ 'description': 'This is my offering',
'design': { '#self': '#self'},
'icon': '/csa/api/blobstore/Magic_RGB_blue_NT.png?tag=library',
'name': 'name',
'version': '1.0.0'}
>>>
JSON dumps:
import json
data={"name":'name',"description": "This is my offering","icon":"/csa/api/blobstore/Magic_RGB_blue_NT.png?tag=library","version": "1.0.0","design": {"#self": "#self"}}
print(json.dumps(data, indent=4))
>>>
{
"icon": "/csa/api/blobstore/Magic_RGB_blue_NT.png?tag=library",
"design": {
"#self": "#self"
},
"name": "name",
"version": "1.0.0",
"description": "This is my offering"
}
>>>
If you are concerned about the the order in which the items are printed, then you'll need to have an array that stores the keys in their preferred order (dictionaries don't have any inherant ordering), and then iterate through your keys and print the dictionary items out manually one by one (perhaps using a list comprehension on your keys array).

Python doesn't respect the indention or newlines you use to define your data structure, and ignores any format you had when print()ing it. You don't have very many options here, but perhaps you can use the json.dumps() function to format your code. The format does not match your expected output exactly, but it comes fairly close:
>>> data = {"name":'name',"description": "This is my offering","icon":"/csa/api/blobstore/Magic_RGB_blue_NT.png?tag=library","version": "1.0.0",
"design": {
"#self": "#self"
}
}
>>> import json
>>> print(json.dumps(data, indent=2))
{
"description": "This is my offering",
"version": "1.0.0",
"icon": "/csa/api/blobstore/Magic_RGB_blue_NT.png?tag=library",
"name": "name",
"design": {
"#self": "#self"
}
}
>>>

Note that a variable doesn't contain any formatting to be changed. The python interpreter reads text from the REPL or a file and turns them into instructions for the CPU of your machine. None of this involves formatting until you call print(). By default, print() calls str() which then provides some very basic formatting. For dictionaries, this includes the curly braces, colons, and commas. If you want anything more than this, you will need to do it yourself. Alternatively, you can find a Python module that helps reduce some of the tedium.

Related

Write JSON for corresponding XML

I want to write JSON code which can be converted in fix format kind of XML
<function>foo
<return>uint32_t</return>
<param>count
<type>uint32_t</type>
</param>
</function>
I have tried multiple ways to develop a JSON which can be formatted like as in above but failed to get perfection because no separate key is required for foo and count which are orphan values otherwise.
Tried ways:
Way 1:
{
"function" :
{"foo":
{"return":"uint32_t"},
"param":
{"count":
{"type":"uint32_t"}
}
}
}
Way 2:
{
"function" :
["foo",{"return":"uint32_t"}],
"param":
["count",{"type":"uint32_t"}]
}
Way 3: But i do not need name tag :(
{
"function":
{"name": "foo",
"return": "uint32_t",
"param": "count",
"type": "uint32_t"
}
}
For generating output and testing please use:
JSON to XML convertor
Requesting your help.. I later have a script to convert the formatted excel to C header files.
It is very rare for a JSON-to-XML conversion library to give you precise control over the XML that is generated, or conversely, for an XML-to-JSON converter to give you precise control over the JSON that is generated. It's basically not possible because the data models are very different.
Typically you have to accept what the JSON-to-XML converter gives you, and then use XSLT to transform it into the flavour of XML that you actually want.
(Consider using the json-to-xml() conversion function in XSLT 3.0 and then applying template rules to the result.)

Python json.loads changes the order of the object

I've got a file that contains a JSON object. It's been loaded the following way:
with open('data.json', 'r') as input_file:
input_data = input_file.read()
At this point input_data contains just a string, and now I proceed to parse it into JSON:
data_content = json.loads(input_data.decode('utf-8'))
data_content has the JSON representation of the string which is what I need, but for some reason not clear to me after json.loads it is altering the order original order of the keys, so for instance, if my file contained something like:
{ "z_id": 312312,
"fname": "test",
"program": "none",
"org": null
}
After json.loads the order is altered to let's say something like:
{ "fname": "test",
"program": None,
"z_id": 312312,
"org": "none"
}
Why is this happening? Is there a way to preserve the order? I'm using Python 2.7.
Dictionaries (objects) in python have no guaranteed order. So when parsed into a dict, the order is lost.
If the order is important for some reason, you can have json.loads use an OrderedDict instead, which is like a dict, but the order of keys is saved.
from collections import OrderedDict
data_content = json.loads(input_data.decode('utf-8'), object_pairs_hook=OrderedDict)
This is not an issue with json.load. Dictionaries in Python are not order enforced, so you will get it out of order; generally speaking, it doesn't matter, because you access elements based on strings, like "id".

How to copy a python script which includes dictionaries to a new python script?

I have a python script which contains dictionaries and is used as input from another python script which performs calculations. I want to use the first script which is used as input, to create more scripts with the exact same structure in the dictionaries but different values for the keys.
Original Script: Car1.py
Owner = {
"Name": "Jim",
"Surname": "Johnson",
}
Car_Type = {
"Make": "Ford",
"Model": "Focus",
"Year": "2008"
}
Car_Info = {
"Fuel": "Gas",
"Consumption": 5,
"Max Speed": 190
}
I want to be able to create more input files with identical format but for different cases, e.g.
New Script: Car2.py
Owner = {
"Name": "Nick",
"Surname": "Perry",
}
Car_Type = {
"Make": "BMW",
"Model": "528",
"Year": "2015"
}
Car_Info = {
"Fuel": "Gas",
"Consumption": 10,
"Max Speed": 280
}
So far, i have only seen answers that print just the keys and the values in a new file but not the actual name of the dictionary as well. Can someone provide some help? Thanks in advance!
If you really want to do it that way (not recommended, because of the reasons statet in the comment by spectras and good alternatives) and import your input Python file:
This question has answers on how to read out the dictionaries names from the imported module. (using the dict() on the module while filtering for variables that do not start with "__")
Then get the new values for the dictionary entries and construct the new dicts.
Finally you need to write a exporter that takes care of storing the data in a python readable form, just like you would construct a normal text file.
I do not see any advantage over just storing it in a storage format.
read the file with something like
text=open('yourfile.py','r').read().split('\n')
and then interpret the list of strings you get... after that you can save it with something like
new_text = open('newfile.py','w')
[new_text.write(line) for line in text]
new_text.close()
as spectras said earlier, not ideal... but if that's what you want to do... go for it

How do I keep the JSON key order fixed with Python 3 json.dumps?

I've noticed some strange behavior on Python 3's implementation of json.dumps, namely the key order changes every time I dump the same object from execution to execution. Googling wasn't working since I don't care about sorting the keys, I just want them to remain the same! Here is an example script:
import json
data = {
'number': 42,
'name': 'John Doe',
'email': 'john.doe#example.com',
'balance': 235.03,
'isadmin': False,
'groceries': [
'apples',
'bananas',
'pears',
],
'nested': {
'complex': True,
'value': 2153.23412
}
}
print(json.dumps(data, indent=2))
When I run this script I get different outputs every time, for example:
$ python print_data.py
{
"groceries": [
"apples",
"bananas",
"pears"
],
"isadmin": false,
"nested": {
"value": 2153.23412,
"complex": true
},
"email": "john.doe#example.com",
"number": 42,
"name": "John Doe",
"balance": 235.03
}
But then I run it again and I get:
$ python print_data.py
{
"email": "john.doe#example.com",
"balance": 235.03,
"name": "John Doe",
"nested": {
"value": 2153.23412,
"complex": true
},
"isadmin": false,
"groceries": [
"apples",
"bananas",
"pears"
],
"number": 42
}
I understand that dictionaries are unordered collections and that the order is based on a hash function; however in Python 2 - the order (whatever it is) is fixed and doesn't change on a per-execution basis. The difficulty here is that it's making my tests difficult to run because I need to compare the JSON output of two different modules!
Any idea what is going on? How to fix it? Note that I would like to avoid using an OrderedDict or performing any sorting and what matters is that the string representation remains the same between executions. Also this is for testing purposes only and doesn't have any effect on the implementation of my module.
Python dictionaries and JSON objects are unordered. You can ask json.dumps() to sort the keys in the output; this is meant to ease testing. Use the sort_keys parameter to True:
print(json.dumps(data, indent=2, sort_keys=True))
See Why is the order in Python dictionaries and sets arbitrary? as to why you see a different order each time.
You can set the PYTHONHASHSEED environment variable to an integer value to 'lock' the dictionary order; use this only to run tests and not in production, as the whole point of hash randomisation is to prevent an attacker from trivially DOS-ing your program.
This behavior changed in Python 3.7. The json documentation says this:
Prior to Python 3.7, dict was not guaranteed to be ordered, so inputs and outputs were typically scrambled unless collections.OrderedDict was specifically requested. Starting with Python 3.7, the regular dict became order preserving, so it is no longer necessary to specify collections.OrderedDict for JSON generation and parsing.
The story behind this behavior is this vulnerability. To prevent it, same hash codes on one PC should be different on another one.
Python 2 has probably disabled this behavior (hash randomizing) by default because of compatibility, as this would for example break doctests. Python 3 probably (an assumption) has not needed the compability.

How can I edit a JSON element in-place, without rewriting the rest of the JSON object?

I am receiving several objects, currently in JSON, and need to be able to modify parts of them, while leaving the later parts EXACTLY, space for space, bit for bit, identical.
For instance, Imagine I was receiving following object
{
"example": [
{
"Name": "Thing One",
"Line2": "more text. ABCD\nEFG"
},
{
"Name": "Thing Two",
"Line2": "XYZZY..."
}
{
"Name": "Thing Three",
"Line2": [
{
"SubElement": "Sub1",
"SubElement": "Sub2"
]
}
]
}
If I want to the JSON object such that "Thing One" reads "Thing 111" while leaving Thing Three EXACTLY the way it is right now, is there any way to do that?
Right now, I'm converting it to a dictionary, modifying the element, then converting it back, but that doesn't work well for this scenario.
My fallback position is to convert to XML and use Regexes, but that's ugly.
The object_pairs_hook argument of the json load functions will allow you to use a OrderedDictionary such that you can retain the same order of the elements of JSON objects.
The best answer to this question may be "Don't Do that."
If I need the bits to remain identical, I can replace "Thing Three" with a BASE64 or yENC encoded version of itself.
My current solution to this problem is to require the JSON to be in the most compact format. No whitespace, ;:, etc.
Reformatting it should be OK, so long as we always reformat to the same thing.

Categories