3

This is my first question here, I'm new to python and trying to figure some things out to set up an automatic 3D model processing chain that relies on data being stored in JSON files moving from one server to another.

The problem is that I need to store absolute paths to files that are being processed, but these absolute paths should be modified in the original JSON files upon the first time that they are processed.

Basically the JSON file comes in like this:

{
    "normaldir": "D:\\Outgoing\\1621_1\\", 
  "projectdir": "D:\\Outgoing\\1622_2\\"
} 

And I would like to rename the file paths to

    {
"normaldir": "X:\\Incoming\\1621_1\\", 
  "projectdir": "X:\\Incoming\\1622_2\\", 
   } 

What I've been trying to do is replace the first part of the path using this code, but it isn't working:

def processscan(scanfile):
    configfile= MonitorDirectory + scanfile
    with open(configfile, 'r+') as file:
        content = file.read()
        file.seek(0)
        content.replace("D:\\Outgoing\\", "X:\\Incoming\\")
        file.write(content)

However this was not working at all, so I tried interpreting the JSON file properly and replacing the key code from here:

def processscan(scanfile):
    configfile= MonitorDirectory + scanfile
    with open(configfile, 'r+') as settingsData:
        settings = json.load(settingsData)  
        settings['normaldir'] = 'X:\\Incoming\\1621_1\\'
        settings['projectdir'] = 'X:\\Incoming\\1622_2\\'
        settingsData.seek(0)  # rewind to beginning of file
        settingsData.write(json.dumps(settings,indent=2,sort_keys=True)) #write the updated version 
        settingsData.truncate() #truncate the remainder of the data in the file

This works perfectly, however I'm replacing the whole path so it won't really work for every JSON file that I need to process. What I would really like to do is to take a JSON key corresponding to a file path, keep the last 8 characters and replace the rest of the patch with a new string, but I can't figure out how to do this using json in python, as far as I can tell I can't edit part of a key. Does anyone have a workaround for this?

Thanks!

1
  • Dictionaries consist of key, value pairs. You want to modify the values, not the keys. Commented Jul 6, 2016 at 19:30

3 Answers 3

4

Your replace logic failed as you need to reassign content to the new string,str.replace is not an inplace operation, it creates a new string:

 content =  content.replace("D:\\Outgoing\\", "X:\\Incoming\\")

Using the json approach just do a replace too, using the current value:

settings['normaldir'] =  settings['normaldir'].replace("D:\\Outgoing\\", "X:\\Incoming\\")

You also would want truncate() before you write or just reopen the file with w and dump/write the new value, if you really wanted to just keep the last 8 chars and prepend a string:

settings['normaldir'] =  "X:\\Incoming\\" + settings['normaldir'][-8:] 
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! This works perfectly, except I had to use [-8:] to keep only the last part of the string!
1

Python come with a json library. With this library, you can read and write JSON files (or JSON strings). Parsed data is converted to Python objects and vice versa.

To use the json library, simply import it:

import json

Say your data is stored in input_data.json file.

input_data_path = "input_data.json"

You read the file like this:

import io

with io.open(input_data_path, mode="rb") as fd:
    obj = json.load(fd)

or, alternatively:

with io.open(input_data_path, mode="rb") as fd:
    content = fd.read()
obj = json.loads(content)

Your data is automatically converted into Python objects, here you get a dict:

print(repr(obj))
# {u'projectdir': u'D:\\Outgoing\\1622_2\\',
#  u'normaldir': u'D:\\Outgoing\\1621_1\\'}

note: I'm using Python 2.7 so you get the unicode string prefixed by "u", like u'projectdir'.

It's now easy to change the values for normaldir and projectdir:

obj["normaldir"] = "X:\\Incoming\\1621_1\\"
obj["projectdir"] = "X:\\Incoming\\1622_2\\"

Since obj is a dict, you can also use the update method like this:

obj.update({'normaldir': "X:\\Incoming\\1621_1\\",
            'projectdir': "X:\\Incoming\\1622_2\\"})

That way, you use a similar syntax like JSON.

Finally, you can write your Python object back to JSON file:

output_data_path = "output_data.json"

with io.open(output_data_path, mode="wb") as fd:
    json.dump(obj, fd)

or, alternatively with indentation:

content = json.dumps(obj, indent=True)
with io.open(output_data_path, mode="wb") as fd:
    fd.write(content)

Remarks: reading/writing JSON objects is faster with a buffer (the content variable).

Comments

1

.replace returns a new string, and don't change it. But you should not treat json-files as normal text files, so you can combine parsing json with replace:

def processscan(scanfile):
    configfile= MonitorDirectory + scanfile
    with open(configfile, 'rb') as settingsData:
        settings = json.load(settingsData)

    settings = {k: v.replace("D:\\Outgoing\\", "X:\\Incoming\\")
        for k, v in settings.items()
    }

    with open(configfile, 'wb') as settingsData:
        json.dump(settings, settingsData)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.