is it possible to convert each part of dictionary to json separately put them together as valid json?

Question:

Is it possible to convert each value pair of a dictionary into json
and then put them back together as one JSON, I tried doing it as such but it failed and produced weird:

def toj(dict):
  j=[]
  for k,v in dict.items():
      try:
         j.append({json.dumps(k):json.dumps(v)})
      except:
         j.append({json.dumps(k):json.dumps(str(v))})
  return j

why do I need it? –>

I need to pass around dictionary instance within my app which is currently using Flask as the web framework (It may change in the future).

from datetime import datetime
dic={'1':One, 2:'Two','list1':[1,2,3],'time_stamp':datetime.now()} 

This dictionary is not json convertible as you all would know:

    raise TypeError(f'Object of type {o.__class__.__name__} '

               f'is not JSON serializable')

TypeError: Object of type datetime is not JSON serializable

Json.dumps acts on the entire object and not each key.So either the whole thing has to be sanitized.

Lucky for me, I I can solve this by converting the offending object into str.
but this is not possible because

  1. I do not know which field will be the offending one as the
    dictionary is created dynamically and can be any length really
  2. I can not check for type datetime only because it could be one of many objects which can be of any type but all have str implementd
  3. I can not convert the whole dict to str as then converting it back to dict causes odd issues.
  4. JUST fyi For very complicated reasons I can not use any other library than json itself.
  5. Passing a default does not help, because I can not change the class OF THE object I am passing into dumps and again JSON.dumps takes the whole object not pieces of it

Full-disclosure—> my brain does not digest json easily

Asked By: Max

||

Answers:

from datetime import datetime

def toj(dict):
    conversions = {datetime: str}
    for k, v in dict.items():
        for instance, conv in conversions.items():
            if isinstance(v, instance):
                dict[k] = conv(v)
    return json.dumps(dict)

You can update conversions according to your requirements.

Execution:

In [1]: d = {'1':'One', 2:'Two','list1':[1,2,3],'time_stamp':datetime.now()}

In [2]: toj(d)
Out[2]: '{"1": "One", "2": "Two", "list1": [1, 2, 3], "time_stamp": "2022-10-10 00:39:00.604636"}'

Edit:

Based on your comment if all have string methods available you can do this.

def toj(dict):
    for k, v in dict.items():
        try:
            json.dumps(v)
        except (TypeError, OverflowError):
            dict[k] = v.__str__()
    return json.dumps(dict)
Answered By: Rahul K P

you can easily do this with default keyword of json.dump

def handle_conversion(v):
    if isinstace(v,datetime):
       return str(v)
    elif isinstance(v,some_other_thing_that_cannot_be_jsonified):
       return "???" # a value that can be jsonified
    return v

data = json.dumps(a_dict_with_datetimes,default=handle_conversion)

if you only need to pass serialized data between python you can use the pickle module instead which serialized almost anything (but sometimes breaks depending on where you are decoding it)

here is a complete working example

import json
from datetime import datetime


class some_other_thing_that_cannot_be_jsonified:
    pass


def handle_conversion(v):
    if isinstance(v,datetime):
       return str(v)
    elif isinstance(v,some_other_thing_that_cannot_be_jsonified):
       return "???" # a value that can be jsonified
    return v


a_dict_with_datetimes = {
    "dt":datetime.now(),"a":"hello","w":"world","L":[1,2,3]
}

data = json.dumps(a_dict_with_datetimes,default=handle_conversion)
print(data)
# {"dt": "2022-10-09 16:21:19.643080", "a": "hello", "w": "world", "q": [1, 2, 3]}

you could simplify it to also just always return str (it only calls default if it could not jsonify the object), this will cause any object that cannot be jsonified to be converted to str

def handle_conversion(v):
    # if isinstance(v,datetime):
    #    return str(v)
    # elif isinstance(v,some_other_thing_that_cannot_be_jsonified):
    #    return "???" # a value that can be jsonified
    return str(v)
Answered By: Joran Beasley
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.