0

I have a dict object with this type of structure

{"a": '{"b": "c"}'}

I'd like to use a loop to insert different values into the "c" area for use elsewhere in a project. The problem is that the single quotes around the b and c make this more difficult.

I tried:

{"a": '{"b": "{}"}.format("d")'}

But this returns the dict without evaluating the format function.

I also tried:

{"a": '{"b": "{}"}'.format("d")}

But this returns an error. I've gone through 2 hours of combinations and SO questions like (this, this, and this) but have realized that I need the help of someone who knows what they're doing.

A viable solution would look like:

x = {"a": '{"b": "c"}'}
val = "d"

magic(x, val)

>>> {"a": '{"b": "d"}'}

Note: To the comments asking "why this format"? I am not creating these objects and so they are not my choice. I have an api that I have connected to. I am pulling the current data, changing it, and uploading it back. There is no opportunity to "not use a string literal". That is what the api post is expecting. I am not in a position now to ask the maintainers to change their storage system

Pierre L
  • 28,203
  • 6
  • 47
  • 69
  • Have you tried `eval`? – Wakeme UpNow Jan 31 '19 at 09:43
  • 1
    Why you want your values to be a string representation of a dict rather than a dict? – Chris_Rands Jan 31 '19 at 09:43
  • When you have a string value you use the quotes around it, but when you have a non-string value there should be no quotes. So for instance an integer value is `{'a':2}`, and similar if the value is a dict, you should not have the quotes around the value, so use `{'a':{'b':'c'}}`. – Vincent Jan 31 '19 at 09:45
  • To the comments asking "why"? I am not creating these objects and so they are not my choice. I have an api that I have connected to. I am pulling the current data, changing it, and uploading it back. There is no opportunity to "not use a string literal". That is what the api post is expecting. I am not in a position now to ask the maintainers to change their storage system – Pierre L Jan 31 '19 at 17:38

4 Answers4

3

This should work for you

import json
obj = {"a": '{"b": "c"}'}
inner_a = json.loads(obj['a'])
inner_a['b'] = 'd'
obj['a'] = json.dumps(inner_a)
redacted
  • 3,789
  • 6
  • 25
  • 38
0

Try this:

import ast
x = {"a": '{"b": "c"}'}
a = ast.literal_eval(x['a'])
a['b'] = 'd'
x['a'] = str(a)

And now:

print(x)

Is:

{"a": '{"b": "d"}'}
U13-Forward
  • 69,221
  • 14
  • 89
  • 114
  • This works for the OP's (I suppose) greatly simplified problem, but I bet it wouldn't be useful for anything else. How about `{"a": '{"c": "c"}'}`? – redacted Jan 31 '19 at 09:50
  • My point is, OP is clearly dealing with json strings so using anything else than `json` to manipulate it seems pointless – redacted Jan 31 '19 at 09:54
  • @RobinNemeth is correct this is a cool looking solution but does not address the issue presented. As seen in the example, "c", or more broadly, the original value is not an input in the `magic` function. This is important because the value will be unknown when replaced – Pierre L Jan 31 '19 at 20:22
  • @RobinNemeth Edited mine. – U13-Forward Feb 01 '19 at 00:56
  • @PierreLafortune Edited mine. – U13-Forward Feb 01 '19 at 00:56
0

You are trying to build a string literal, when it would be easier to just build a dict directly; there is no need for the values in a dict literal them selves to be literals. The problem is that the value of d['a'] is a string rather than a dict. Is this really necessary? For a simple dictionary you could simply use:

>>> def magic(d, val):
...     d['a']['b'] = val
...
>>> my_dict = {"a": {"b": "c"}}  # my_dict['a'] is also a dict
>>> magic(my_dict, 'd')
>>> my_dict
{'a': {'b': 'd'}}
>>> magic(my_dict, {'x': 1, 'y' :2, 'z': 3})
>>> my_dict
{'a': {'b': {'x': 1, 'y': 2, 'z': 3}}}

When the value is a string, however, much depends on its format. If the keys are all strings and the values are strings or numbers then you could use the json module to convert it into a dict, operate on it and place it back:

>>> import json
>>> def smagic(d, val):
...     inner = json.loads(d['a'])
...     inner['b'] = val
...     d['a'] = json.dumps(inner)
...
>>> my_dict = {"a": '{"b": "c"}'}  # my_dict['a'] is a string
>>> smagic(my_dict, "Is this it?")
>>> my_dict
{'a': '{"b": "Is this it?"}'}

You could extend this solution by using repr and eval, but I would advise against that level of complexity unless there is no way to avoid it.

holdenweb
  • 33,305
  • 7
  • 57
  • 77
-1
#use this code according for reference
print("enter name\n") 
n1=input("enter 1st name ")
ln=input("enter last name ")
add=input("enter address ")
dic={'name':{"1st name":n1,"lname":ln},'address':add}
print(dic.values())
print(dic)