-3

I'm finding it difficult to turn a json like string into a json/dict object, I've got the data like this

{"key1":"value1","key2":[{"key2.1":"value2.1"},{"key2.2":"value2.2"}]}

When running type on the variable it tells me it is of class str i.e <class 'str'>. I need to get the string into a json or dict like format so I can extract all of the values named value...

I've tried json.loads, json.load, json.dumps, ast.literal_eval but nothing seems to be working. I've tried adding [' and '] either side of the string but still no luck. Any ideas? Thanks

EDIT:

I'm using a nodeJS backend sending a request to a flask server, the nodeJS axios request is this

get_values: (key_one, key_two) =>
  axios.post('http://localhost:5000/example', {
    key_one: key_one,
    key_two: key_two
  }).then(res => res.data),

on the flask side I'm doing this

@app.route('/example', methods=["POST","OPTIONS"])
def example():
  convert_data = request.get_data()
  string_data = convert_data.decode('utf8').replace("'", '"')
  new_string = "'''" + string_data + "'''"
  print(json.loads(new_string))

Then I get the an error

w13rfed
  • 355
  • 5
  • 12
  • "Nothing seems to be working" - How is it failing? What do you get? `json.loads` and `ast.literal_eval` should both work just fine on your example input. Are you sure they're failing? Example: `json.loads('{"key1":"value1","key2":[{"key2.1":"value2.1"},{"key2.2":"value2.2"}]}')` produces the expected `dict`. – ShadowRanger Mar 27 '18 at 02:47
  • 1
    the `{"key1":"value1","key2":[{"key2.1":"value2.1"},{"key2.2":"value2.2"}]}` you provided is already a `dict`, why do you still need to serialize it? – MaThMaX Mar 27 '18 at 02:47
  • @ShadowRanger running that gives a long output the last line of which is `json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)` – w13rfed Mar 27 '18 at 02:51
  • @MaThMaX running `print(my_string.get('key1'))` gives the output `AttributeError: 'str' object has no attribute 'get'` – w13rfed Mar 27 '18 at 02:52
  • I ran `json.loads(s)` with `s = '''{"key1":"value1","key2":[{"key2.1":"value2.1"},{"key2.2":"value2.2"}]}'''`. No problem. – mshsayem Mar 27 '18 at 02:53
  • As @mshsayem says, it works for your example, but I suspect your example isn't remotely related to what you're actually doing. Post a [MCVE]; as is, it's impossible to answer your question (because `json.loads` *works* for what you've provided). – ShadowRanger Mar 27 '18 at 02:56
  • @ShadowRanger Hopefully it should be complete now – w13rfed Mar 27 '18 at 03:05
  • What error you get ? – kip Mar 27 '18 at 03:08
  • @kip same as the errors in my first comment, starts with `[2018-03-27 03:55:33,110] ERROR in app: Exception on /example [OPTIONS]` ends with `json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)` it's a fairly large error – w13rfed Mar 27 '18 at 03:09
  • The only other piece of information from the error that seems to be of use is `raise JSONDecodeError("Expecting value", s, err.value) from None` which is the penultimate line from the error if that helps – w13rfed Mar 27 '18 at 03:12
  • @W22 I think that you need to use `request.form['key']` to get the `POST` values, if the `POST` send the data like `JSON` in the body request then you can try with `request.get_json()` – kip Mar 27 '18 at 03:20
  • Why are you replacing single quotes? – mshsayem Mar 27 '18 at 03:23
  • @kip `request.form['key']` gives me errors, `request.get_json()` works however I'm struggling to get further information from it, I'm running into the error `TypeError: 'NoneType' object is not subscriptable`, which I've tried before to solve before by adding headers to the request, i'll try again unless there's a different way of getting the information? – w13rfed Mar 27 '18 at 03:30
  • @mshsayem Following previous answers on stackoverflow about getting a string into json format – w13rfed Mar 27 '18 at 03:31

2 Answers2

1

I modified your function a bit:

@app.route('/example', methods=["POST","OPTIONS"])
def example():
  convert_data = request.get_data()
  string_data = convert_data.decode('utf8')
  print(json.loads(string_data))

It seems string_data is already a perfectly formatted json string that you can pass into loads. I removed the replacement of ' with " which seems unnecessary, and definitely the addition of ''', which will make this string become Python multiline string literal syntax but definitely break json compatibility, which is what your error tells you too:

json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

This should be a lot closer to what you wanted. Otherwise let me know what exactly is inside string_data when you run this.

Jeronimo
  • 2,268
  • 2
  • 13
  • 28
  • It runs into an error on the final line, first line of error `Error on request:` followed by a fairly large error about random library calls then ends with `raise JSONDecodeError("Expecting value", s, err.value) from None json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)` – w13rfed Mar 27 '18 at 10:05
  • When running `type(string_data)` I get `` and the output is`{"key1":"value1","key2":[{"key2.1":"value2.1"},{...`. – w13rfed Mar 27 '18 at 10:12
  • Looking good actually. Maybe it's the encoding... Have you tried `string_data = request.get_data(as_text=True)`? – Jeronimo Mar 27 '18 at 11:28
  • The request itself works, trying to use `string_data['key1']` gets the error `TypeError: string indices must be integers`. Trying `string_data.get('key1')` has the error `AttributeError: 'str' object has no attribute 'get'`. Trying `json.loads(string_data)` gets the error `json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)`. I've found a solution using regex' and other things to solve the issue but still not good I guess, using `request.form.get('key1')` doesn't crash but it prints `None`. – w13rfed Mar 27 '18 at 22:25
  • Ofc `string_data` is a string so none of the getitem (dict-like) access works, but if the content is indeed a valid json string, there should be no trouble parsing it with `json.loads`. Must be something wrong with it. Can you show me a full `print(string_data.__repr__())`? – Jeronimo Mar 28 '18 at 08:06
-1

Not sure if I understand the question correctly. But, let's say you have a string as follows:

var a = { "key1": "value1", "key2": [{ "key2.1": "value2.1" }, { "key2.2": "value2.2" }] }

Then you can do something like this:

try {
  const dictionary = JSON.parse(a)

  console.log(dictionary.key1) // This will print value1

  Object.keys(dictionary).map((key) => {
    console.log(dictionary[key]);
  });

} catch(e){
    // do something with error here
}
Matt Rowles
  • 7,721
  • 18
  • 55
  • 88