-
Notifications
You must be signed in to change notification settings - Fork 333
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace Values for some keys given a map #449
base: master
Are you sure you want to change the base?
Conversation
This functionallity adds to JoltUtils the capability to change the value of one or more nodes given a map where the key match with a node key, and the value is the new content for that node.key. Two methods added: JoltUtils.replaceRecursive -> Which receive a Jackson Object a Key and a value to replace JoltUtils.replaceValues -> Which receive a Jackson Object and a Map with several Keys and Values to replace. Example: Given: { "L1_A": { "L2_A": { "L3_A": "Good", "L3_B": "RemoveThis" }, "L2_B": "l2_b" }, "L1_B": "l1_b", "L3_B": "RemoveThis" } When: // java code Map<String, Object> params = new HashMap<>(); params.put("L3_A", String.valueOf(j)); params.put("L3_B", String.valueOf(j)); // data is a Jackson Object JoltUtils.replaceValues(data, params); Then: { "L1_A": { "L2_A": { "L3_A": "Replaced1", "L3_B": "Replaced2" }, "L2_B": "l2_b" }, "L1_B": "l1_b", "L3_B": "Replaced2" }
*/ | ||
public static void replaceValues(Object json, Map<String, Object> params){ | ||
for(String key : params.keySet()) { | ||
replaceRecursive(json, key, params.get(key)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This loops over the whole input tree for each key. It should ideally only recurse thru the content once.
Could at each level compare the input keyset and the replacementMapKeyset.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now first I look for the parent node and then apply the replacement, please take a look on my updates and tell me if you think something else could be changed.
* @param keyToReplace the key to remove from the document | ||
* @param value the new value for the keyToReplace | ||
*/ | ||
public static void replaceRecursive( Object json, String keyToReplace, Object value ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is more of an "updateValueRecursive" or "replaceValueRecursive"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to replaceValueRecursive
@@ -62,6 +62,54 @@ public static void removeRecursive( Object json, String keyToRemove ) { | |||
} | |||
|
|||
/** | |||
* Replaces a value recursively from anywhere in a JSON document. | |||
* NOTE: mutates its input. | |||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pls add a small example in the javadoc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
Map<String,Object> toReplace = (Map<String, Object>)testUnit.get( "replace" ); | ||
Object expected = testUnit.get( "expected" ); | ||
|
||
for(String key : toReplace.keySet()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is clever in that it is using the same test fixture to test two methods, but it would be simpler to understand if this test only changed one key / had a separate test fixture where only one key got replaced/updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now I removed this test and just test the replace value, since now we can give a path for each key to be replaced and a set of values that can be replaced.
Now we can provide the full path where the replacement will be done, and a map to match the values to be replaced. Given the next example: { "input" : { "L1_A" : { "L2_A" : { "L3_A" : "Good", "L3_B" : "ReplaceThis" }, "L2_B" : "l2_b" }, "L1_B" : "l1_b", "L3_B" : "This not should be replaced" }, "mappingPaths" : { "L3_B" : ["L1_A.L2_A.L3_B"] }, "valuesToReplace" : { "L3_B" : { "ReplaceThis" : "This has been replaced." } }, "expected" : { "L1_A" : { "L2_A" : { "L3_A" : "Good", "L3_B" : "This has been replaced." }, "L2_B" : "l2_b" }, "L1_B" : "l1_b", "L3_B" : "This not should be replaced" } } The 'input' is the original json, the 'mappingPaths' is a map where each key contains a list of fullpaths (a fullpath is the human reading representation of a node from json object) the 'values' to replace is a map that contains a map where each key contains a map that represents the { "oldValue" : "newValue" } elements if the old value matches in the key where then it will be replaced with the new value, if not it will be ignored.
Merge latest changes.
This implementation is added for special cases where we don't know the exact value to replace but by default we wan't a replacement. Given the next example: { "input" : { "L1_A" : { "L2_A" : { "L3_A" : "Good", "L3_B" : "ReplaceThis" }, "L2_B" : "l2_b" }, "L1_B" : "l1_b", "L3_B" : "Replace any content" }, "mappingPaths" : { "L3_B" : [ "L1_A.L2_A.L3_B", "L3_B" ] }, "valuesToReplace" : { "L3_B" : { "ReplaceThis" : "This has been replaced.", "*" : "The star replace any content" } }, "expected" : { "L1_A" : { "L2_A" : { "L3_A" : "Good", "L3_B" : "This has been replaced." }, "L2_B" : "l2_b" }, "L1_B" : "l1_b", "L3_B" : "The star replace any content" } } On the main structure at "L3_B" key the "*" means that no mather what is the old value it will be replaced with the text "The star replace any content".
@milosimpson I made a few changes to my code and maybe I wasn't able to explain myself clearly in the comments, maybe I can have feedback via Skype or Hangouts if you want, let me know if you have time. |
Conflicts solved. |
This functionallity adds to JoltUtils the capability to change the value
of one or more nodes given a map where the key match with a node key, and the
value is the new content for that node.key.
Two methods added:
JoltUtils.replaceValues -> Receives a Map with the keys and values to replace in a Jackson Object.
Example:
Given:
When:
Then: