added possibility to specify non existing elements

This commit is contained in:
dashevchenko 2023-02-12 23:40:12 +02:00
parent 4a9c4cc614
commit f812e02920
2 changed files with 46 additions and 14 deletions

View File

@ -778,41 +778,68 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest {
JsonNode expectedSettings = mapper.readTree("{\"A\":10, \"B\":{\"C\":true, \"D\":\"stringValue\"}}"); JsonNode expectedSettings = mapper.readTree("{\"A\":10, \"B\":{\"C\":true, \"D\":\"stringValue\"}}");
Assert.assertEquals(expectedSettings, updatedSettings); Assert.assertEquals(expectedSettings, updatedSettings);
JsonNode patchedSettings = mapper.readTree("{\"B\":{\"C\":false, \"D\":\"stringValue2\"}}"); JsonNode patchedSettings = mapper.readTree("{\"A\":11, \"B\":{\"C\":false, \"D\":\"stringValue2\"}}");
doPut("/api/user/settings", patchedSettings); doPut("/api/user/settings", patchedSettings);
updatedSettings = doGet("/api/user/settings", JsonNode.class); updatedSettings = doGet("/api/user/settings", JsonNode.class);
expectedSettings = mapper.readTree("{\"A\":10, \"B\":{\"C\":false, \"D\":\"stringValue2\"}}"); expectedSettings = mapper.readTree("{\"A\":11, \"B\":{\"C\":false, \"D\":\"stringValue2\"}}");
Assert.assertEquals(expectedSettings, updatedSettings); Assert.assertEquals(expectedSettings, updatedSettings);
patchedSettings = mapper.readTree("{\"B.D\": \"stringValue3\"}"); patchedSettings = mapper.readTree("{\"B.D\": \"stringValue3\"}");
doPut("/api/user/settings", patchedSettings); doPut("/api/user/settings", patchedSettings);
updatedSettings = doGet("/api/user/settings", JsonNode.class); updatedSettings = doGet("/api/user/settings", JsonNode.class);
expectedSettings = mapper.readTree("{\"A\":10, \"B\":{\"C\":false, \"D\": \"stringValue3\"}}"); expectedSettings = mapper.readTree("{\"A\":11, \"B\":{\"C\":false, \"D\": \"stringValue3\"}}");
Assert.assertEquals(expectedSettings, updatedSettings); Assert.assertEquals(expectedSettings, updatedSettings);
patchedSettings = mapper.readTree("{\"B.D\": {\"E\": 76, \"F\": 92}}"); patchedSettings = mapper.readTree("{\"B.D\": {\"E\": 76, \"F\": 92}}");
doPut("/api/user/settings", patchedSettings); doPut("/api/user/settings", patchedSettings);
updatedSettings = doGet("/api/user/settings", JsonNode.class); updatedSettings = doGet("/api/user/settings", JsonNode.class);
expectedSettings = mapper.readTree("{\"A\":10, \"B\":{\"C\":false, \"D\": {\"E\":76, \"F\": 92}}}"); expectedSettings = mapper.readTree("{\"A\":11, \"B\":{\"C\":false, \"D\": {\"E\":76, \"F\": 92}}}");
Assert.assertEquals(expectedSettings, updatedSettings); Assert.assertEquals(expectedSettings, updatedSettings);
patchedSettings = mapper.readTree("{\"B.D.E\": 100}"); patchedSettings = mapper.readTree("{\"B.D.E\": 100}");
doPut("/api/user/settings", patchedSettings); doPut("/api/user/settings", patchedSettings);
updatedSettings = doGet("/api/user/settings", JsonNode.class); updatedSettings = doGet("/api/user/settings", JsonNode.class);
expectedSettings = mapper.readTree("{\"A\":10, \"B\":{\"C\":false, \"D\": {\"E\":100, \"F\": 92}}}"); expectedSettings = mapper.readTree("{\"A\":11, \"B\":{\"C\":false, \"D\": {\"E\":100, \"F\": 92}}}");
Assert.assertEquals(expectedSettings, updatedSettings); Assert.assertEquals(expectedSettings, updatedSettings);
} }
@Test @Test
public void testShouldNotUpdateUserSettingsWithNoExistingPath() throws Exception { public void testShouldCreatePathIfNotExists() throws Exception {
loginCustomerUser(); loginCustomerUser();
JsonNode userSettings = mapper.readTree("{\"A\":5, \"B\":{\"C\":true, \"D\":\"stringValue\"}}"); JsonNode userSettings = mapper.readTree("{\"A\":5}");
JsonNode savedSettings = doPost("/api/user/settings", userSettings, JsonNode.class); JsonNode savedSettings = doPost("/api/user/settings", userSettings, JsonNode.class);
Assert.assertEquals(userSettings, savedSettings); Assert.assertEquals(userSettings, savedSettings);
JsonNode newSettings = mapper.readTree("{\"A.E\":10}"); JsonNode newSettings = mapper.readTree("{\"B\":{\"C\": 10}}");
doPut("/api/user/settings", newSettings).andExpect(status().isBadRequest()); doPut("/api/user/settings", newSettings);
JsonNode updatedSettings = doGet("/api/user/settings", JsonNode.class);
JsonNode expectedSettings = mapper.readTree("{\"A\":5, \"B\":{\"C\": 10}}");
Assert.assertEquals(expectedSettings, updatedSettings);
newSettings = mapper.readTree("{\"B.K\":true}");
doPut("/api/user/settings", newSettings);
updatedSettings = doGet("/api/user/settings", JsonNode.class);
expectedSettings = mapper.readTree("{\"A\":5, \"B\":{\"C\": 10, \"K\": true}}");
Assert.assertEquals(expectedSettings, updatedSettings);
newSettings = mapper.readTree("{\"B\":{}}");
doPut("/api/user/settings", newSettings);
updatedSettings = doGet("/api/user/settings", JsonNode.class);
expectedSettings = mapper.readTree("{\"A\":5, \"B\":{}}");
Assert.assertEquals(expectedSettings, updatedSettings);
newSettings = mapper.readTree("{\"F.G\":\"string\"}");
doPut("/api/user/settings", newSettings);
updatedSettings = doGet("/api/user/settings", JsonNode.class);
expectedSettings = mapper.readTree("{\"A\":5, \"B\":{}, \"F\":{\"G\": \"string\"}}");
Assert.assertEquals(expectedSettings, updatedSettings);
newSettings = mapper.readTree("{\"F\":{\"G\":\"string2\"}}");
doPut("/api/user/settings", newSettings);
updatedSettings = doGet("/api/user/settings", JsonNode.class);
expectedSettings = mapper.readTree("{\"A\":5, \"B\":{}, \"F\":{\"G\": \"string2\"}}");
Assert.assertEquals(expectedSettings, updatedSettings);
} }
@Test @Test

View File

@ -37,6 +37,7 @@ import org.thingsboard.server.dao.exception.DataValidationException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -135,7 +136,7 @@ public class UserSettingsServiceImpl extends AbstractCachedService<UserId, UserS
Iterator<String> fieldNames = updateNode.fieldNames(); Iterator<String> fieldNames = updateNode.fieldNames();
while (fieldNames.hasNext()) { while (fieldNames.hasNext()) {
String fieldName = fieldNames.next(); String fieldName = fieldNames.next();
validatePathExists(dcOldSettings, fieldName); createPathIfNotExists(dcOldSettings, "$."+ fieldName);
dcOldSettings = dcOldSettings.set("$." + fieldName, getValueByNodeType(updateNode.get(fieldName))); dcOldSettings = dcOldSettings.set("$." + fieldName, getValueByNodeType(updateNode.get(fieldName)));
} }
try { try {
@ -145,11 +146,15 @@ public class UserSettingsServiceImpl extends AbstractCachedService<UserId, UserS
} }
} }
private static void validatePathExists(DocumentContext dcOldSettings, String fieldName) { private static String createPathIfNotExists(DocumentContext dcOldSettings, String path) {
try { try {
dcOldSettings.read("$." + fieldName); dcOldSettings.read(path);
}catch (PathNotFoundException e) { return path;
throw new DataValidationException("Json element with path " + fieldName + "was not found"); } catch (PathNotFoundException e) {
String lastElement = path.substring(path.lastIndexOf(".") + 1);
String pathToLastElement = path.substring(0, path.lastIndexOf("."));
dcOldSettings.put(createPathIfNotExists(dcOldSettings, pathToLastElement), lastElement, new LinkedHashMap<String, Object>());
return path;
} }
} }