Replace Part of a JSON with Other (Using a String Token)

Replace part of a JSON with other (using a string token)

You can use SelectToken to select any item in the JSON object hierarchy. It supports JSONPath query syntax. It returns a JToken corresponding to the value of the selected item, or null if not found. That JToken in turn has a Replace(JToken replacement) method. Thus you can do:

var o1 = JObject.Parse(json);
var o2 = JObject.Parse(json2);

var path = "client.spouse";
o1.SelectToken(path).Replace(o2.SelectToken(path));

var path2 = "client.email";
o1.SelectToken(path2).Replace(o2.SelectToken(path2));

Replacing only a certain part of a JSON object

Json.NET supports "LINQ to JSON" and dynamic access which allows the entire tree to be dealt with dynamically without need for a POCO mapping. This has the advantage over deserializing to typed objects in that additions to the mapping do not need to be accounted for round-trip serialization.

This can be used to parse the JSON, modify the object structure, and then rebuild the JSON text.

Such an approach might look like the following, or it could use one of the other query methods available. (I didn't look much into the actual JSON - eww, btw! - but the query structure should be readily visible after pretty-printing it as appropriate.)

JObject data = JObject.Parse(json);
JObject hero = (JObject)data["hero"];
hero["STR"] = 42; // "god-like strength" hax; modifies the JObject
json = data.ToString(); // re-serialize tree, along with modifications

The dynamic type can also be used for access and manipulation of a Json.NET tree.


Json.NET can work perfectly fine with "odd names", but such names need to be specified with annotations or mapped to a type with dynamic keys such as a Dictionary/JObject.

However, I would not use a POCO route here due to the wide range of names used - it would be stupidly hard/tedious to codify everything into fully early-bound types; that is not to say, however, that the "hero" couldn't be parsed into a specific POCO.

How can I replace tokens in string?

You can just use a match and a single capture group to get the property name that corresponds with the object.

Note that you have to escape the dollar sign and the openings square bracket.

As @Wiktor Stribiżew points out in the comments, you can use || m to return the match in case the group 1 value can not be found in the object.

const item = {
accountsUrl: 'www.google.com',
accountsDomain: 'www.yahoo.com'
}
const regex = /\$ENV\[(\w+)]/
let s = "foo$ENV[accountsDomain]bar";
s = s.replace(regex, (m, g1) => item[g1] || m);
console.log(s);

How can I change the value of a JSON property using Json.NET?

If you just need to modify it for the above JSON model, use JObject.SelectToken to get the parent objects using the JSON path & then set the value like below:

var data = JObject.Parse(json);

var firstColumn = data.SelectToken("summary.summaryDataTable.columns[0]");
var secondColumn = data.SelectToken("summary.summaryDataTable.columns[1]");
firstColumn["title"] = "replacedTitle1";
secondColumn["title"] = "replacedTitle2";

Output:

{
"summary": {
"summaryDataTable": {
"id": "summaryDataTable",
"type": "dataTable",
"source": "/SmartScreen/SummaryFw",
"columns": [
{
"name": "CreateDate",
"title": "replacedTitle1",
"filterable": false
},
{
"name": "CreateUser",
"title": "replacedTitle2",
"filterable": false
}
],
"options": {
"showFilter": false
}
}
}
}

Can I replace part of a string in a JSON key in Python?

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:] 

How can I replace substrings in a string with JSON values in GO?

You can check go regexp for find pattern "%" as your question. However since your string is simple, and you only want substring, replace the value of %paramName. You can only use bytes.Replace to resolve your problem. (I didn't use strings.Replace since there is no need to parse to string).

go playground

package main

import (
"encoding/json"
"log"
"bytes"
)

func main() {
byteValue := []byte(`{
"programBinary" : "/usr/bin/foo",
"extraArgs" : " --arg1=%argumentOne --arg2=%argumentTwo",
"argumentOne" : "foo",
"argumentTwo" : "bar"
}`)
var rawMap map[string]json.RawMessage;
rawErr := json.Unmarshal(byteValue, &rawMap)
if(rawErr != nil) {
log.Printf("JSON Marshalling error (raw): %s\n" , rawErr.Error());
}

byteResult := make([]byte, len(byteValue))
copy(byteResult, byteValue)

for key, value := range rawMap {
stringEscaped := bytes.Replace([]byte(value), []byte("\""), []byte(""), 2);//Can either remove quotes, replace them with single quotes, or escape with \" here
byteResult = bytes.Replace(byteResult, []byte("%"+key), stringEscaped, 1)
}
log.Printf("Result:\n %s", string(byteResult))
}

Replace and add json within another json

You want --slurpfile, and you need to escape /agents/delta part of the path with quotes:

$ jq --slurpfile newval insert.json '.paths."/agents/delta".get.parameters += $newval' main.json
{
"swagger": "2.0",
"paths": {
"/agents/delta": {
"get": {
"description": "lorem ipsum doram",
"operationId": "getagentdelta",
"summary": "GetAgentDelta",
"tags": [
"Agents"
],
"parameters": [
{
"name": "since",
"in": "query",
"description": "Format - date-time (as date-time in RFC3339). The time from which you need changes from. You should use the format emitted by Date's toJSON method (for example, 2017-04-23T18:25:43.511Z). If a timestamp older than a week is passed, a business rule violation will be thrown which will require the client to change the from date. As a best-practice, for a subsequent call to this method, send the timestamp when you <b>started</b> the previous delta call (instead of when you completed processing the response or the max of the lastUpdateOn timestamps of the returned records). This will ensure that you do not miss any changes that occurred while you are processing the response from this method",
"required": true,
"type": "string"
},
{
"name": "Authorization",
"description": "This parameter represents the Authorization token obtained from the OKTA Authorization server. It is the Bearer token provided to authorize the consumer. Usage Authorization : Bearer token",
"in": "header",
"required": true,
"type": "string"
}
]
}
}
}
}

And here's one that first removes any existing Authorization objects from the parameters before inserting the new one into every parameters array, and doesn't depend on an the exact path:

jq --slurpfile newval add.json '.paths |= walk(
if type == "object" and has("parameters") then
.parameters |= map(select(.name != "Authorization")) + $newval
else
.
end)' main.json

How to find and replace a part of a value in json file

I am understanding that you are able to load the file successfully, and all you want to do is replace the strings and save the structure to file again.

For this, we can traverse the list of dictionaries in the data, and modify the value of item['iscategorical'] by replacing $home with the value of item['id'].

We can then dump the modified structure back to (a new) json file.

import json
with open('data.json') as f:
data = json.load(f)

for item in data['maps']:
item['iscategorical'] = item['iscategorical'].replace('$home', item['id'])

with open('new_data.json', 'w') as f:
json.dump(data, f)


Related Topics



Leave a reply



Submit