RedDevil RedDevil - 4 months ago 14
YAML Question

How to link yaml key values to json key values in python

Hi I would like to essentially use yaml data inside json
for eg.

json file:

{
"Name": "foo",
"Birthdate": "1/1/1991",
"Address": "FOO_ADDRESS",
"Note": "Please deliver package to foo at FOO_ADDRESS using COURIER service"
}


yaml file:


---
FOO_ADDRESS: "foo lane, foo state"
COURIER: "foodex"


Could someone please guide me on the most efficient way to do this? In this particular example I don't really need to use a separate yaml file (I understand that). But in my specific case I might have to do that.

Edit: sorry I didnt paste the desired output file

Should look something like this:

{
"Name": "foo",
"Birthdate": "1/1/1991",
"Address": "foo lane, foo state",
"Note": "Please deliver package to foo at foo lane, foo state using foodex service"
}

Answer

To be safe, first load the JSON and then do the replacements in the loaded strings. If you do the replacements in the JSON source, you might end up with invalid JSON output (when the replacement strings contain " or other characters that have to be escaped in JSON).

import yaml, json

def doReplacements(jsonValue, replacements):
  if isinstance(jsonValue, dict):
    processed = {doReplacements(key, replacements): \
        doReplacements(value, replacements) for key, value in \
        jsonValue.iteritems()}
    # Python 3: use jsonValue.items() instead
  elif isinstance(jsonValue, list):
    processed = [doReplacements(item, replacements) for item in jsonValue]
  elif isinstance(jsonValue, basestring):
    # Python 3: use isinstance(jsonValue, str) instead
    processed = jsonValue
    for key, value in replacements.iteritems():
      # Python 3: use replacements.items() instead
      processed = processed.replace(key, value)
  else:
    # nothing to replace for Boolean, None or numbers
    processed = jsonValue
  return processed

input = json.loads("""{
    "Name": "foo",
    "Birthdate": "1/1/1991",
    "Address": "FOO_ADDRESS",
    "Note": "Please deliver package to foo at FOO_ADDRESS using COURIER service"
}
""")

replacements = yaml.safe_load("""---
FOO_ADDRESS: "foo lane, foo state"
COURIER: "foodex"
""")

print json.dumps(doReplacements(input, replacements), indent=2)
# Python 3: `(...)` around print argument

Use json.load and json.dump to read/write files instead of strings. Note that loading and writing the JSON data may change the order of the items in the object (which you should not depend on anyway).

Comments