Reputation: 498
I have the following JSON:
{
"1605855600000":
[
{
"id": "1",
"value": "1. Choice 1",
"checked": true
},
{
"id": "2",
"value": "2. Choice 2",
"checked": false
},
{
"id": "3",
"value": "3. Choice 3",
"checked": false
},
{
"id": "4",
"value": "4. Choice 4",
"checked": false
},
{
"id": "5",
"value": "5. Choice 5",
"checked": false
}
],
"1604732400000":
[
{
"id": "1",
"value": "1. Choice 1",
"checked": false
},
{
"id": "2",
"value": "2. Choice 2",
"checked": false
},
{
"id": "3",
"value": "3. Choice 3",
"checked": false
},
{
"id": "4",
"value": "4. Choice 4",
"checked": false
},
{
"id": "5",
"value": "5. Choice 5",
"checked": false
}
]
}
I'm not sure the exact terminology but the "keys" like '1605855600000' and '1604732400000' are UNIX timestamps that I need to convert in Python.
Here is what I have so far:
def convert_timestamp(obj):
for key in obj.keys():
timestamp = int(key) / 1000
dt_object = datetime.fromtimestamp(timestamp)
date = dt_object.strftime("%B %d, %Y")
new_key = date
if new_key != key:
obj[new_key] = obj[key]
del obj[key]
return obj
data = json.loads(data, object_hook=convert_timestamp)
However, the error I receive says:
ValueError: invalid literal for int() with base 10: 'id'
which means that it is accessing a level below what I am trying to change.
I know the logic inside the definition works to output the string that I need as the final result, but accessing and replacing those with the current logic isn't working.
The final output needs to look something like:
{
"12 November, 2020":
[
{
"id": "1",
"value": "1. Choice 1",
"checked": true
},
...
Upvotes: 2
Views: 354
Reputation: 31710
Here is how I eventually solved it:
json_data = json.loads(data)
dict_keys = json_data.keys()
timestamp = []
for x in dict_keys:
date_val = int(x) / 1000
dt_object = datetime.fromtimestamp(date_val)
date = dt_object.strftime("%B %d, %Y")
timestamp.append(date)
final_dict = dict(zip(timestamp, list(json_data.values())))
Essentially it ended up being easier to pull the keys into a list, perform the transformation, and then merge that list back to the values as the new keys instead of trying to do it in one fell swoop. For someone who has strict performance requirements this might not be ideal but for this use case it will work.
This answer was posted as an edit to the question Transform first level JSON Key with Python - Solved by the OP Hayden under CC BY-SA 4.0.
Upvotes: 0
Reputation: 39404
You are much better off making a new dict
than messing with the keys:
import json
from datetime import datetime
data_str = '''{
"1605855600000":
[
{ "id": "1", "value": "1. Choice 1", "checked": true },
{ "id": "2", "value": "2. Choice 2", "checked": false },
{ "id": "3", "value": "3. Choice 3", "checked": false },
{ "id": "4", "value": "4. Choice 4", "checked": false },
{ "id": "5", "value": "5. Choice 5", "checked": false }
],
"1604732400000":
[
{ "id": "1", "value": "1. Choice 1", "checked": false },
{ "id": "2", "value": "2. Choice 2", "checked": false },
{ "id": "3", "value": "3. Choice 3", "checked": false },
{ "id": "4", "value": "4. Choice 4", "checked": false },
{ "id": "5", "value": "5. Choice 5", "checked": false }
]
}'''
def convert_timestamp(key):
timestamp = int(key) / 1000
dt_object = datetime.fromtimestamp(timestamp)
return dt_object.strftime("%B %d, %Y")
def convert_keys(obj):
return {convert_timestamp(key):val for (key,val) in obj.items()}
data = json.loads(data_str)
new_data = convert_keys(data)
print(new_data)
Output:
{'November 20, 2020': [{'id': '1', 'value': '1. Choice 1', 'checked': True}, {'id': '2', 'value': '2. Choice 2', 'checked': False}, {'id': '3', 'value': '3. Choice 3', 'checked': False}, {'id': '4', 'value': '4. Choice 4', 'checked': False}, {'id': '5', 'value': '5. Choice 5', 'checked': False}], 'November 07, 2020': [{'id': '1', 'value': '1. Choice 1', 'checked': False}, {'id': '2', 'value': '2. Choice 2', 'checked': False}, {'id': '3', 'value': '3. Choice 3', 'checked': False}, {'id': '4', 'value': '4. Choice 4', 'checked': False}, {'id': '5', 'value': '5. Choice 5', 'checked': False}]}
Upvotes: 1
Reputation: 3651
You misused object_hook
parameter in json.loads
.
From the docs
object_hook is an optional function that will be called with the result of any object literal decoded (a dict). The return value of object_hook will be used instead of the dict. This feature can be used to implement custom decoders (e.g. JSON-RPC class hinting).
Therefore, it takes the first object found by the key. As @quamrana mentioned in his answer you need to do:
json_data = json.loads(data)
converted_data = convert_timestamp(json_data)
Also, it is considered a good practice not to override data but use separate variables.
Upvotes: 0
Reputation: 39404
Did you mean:
data = json.loads(data)
data = convert_timestamp(data)
Upvotes: 0