#include <ArduinoJson.h>
String getServerPayload(String sn,String pk,String serverPayload,String path,String payload,bool debug = false)
{
String output = "";
// Parse the JSON strings into DynamicJsonDocument objects
DynamicJsonDocument docP(1024 + (path.length()));
deserializeJson(docP, path);
DynamicJsonDocument doc1(1024 + ((payload.length()) * 2));
deserializeJson(doc1, serverPayload);
DynamicJsonDocument doc2(1024 + ((payload.length()) * 2));
deserializeJson(doc2, payload);
DynamicJsonDocument arrDoc(1024 + ((payload.length()) * 2));
// Create a JSON array
JsonArray arr = arrDoc.to<JsonArray>();
// Create the top-level JSON object with the "sn" and "pk" keys
JsonObject obj = arr.createNestedObject();
// Add the "sn" and "pk" value to there keys
obj["sn"] = sn;
obj["pk"] = pk;
JsonObject root = doc2.as<JsonObject>();
// Create the "components" array and object with a large enough capacityto store Json
JsonArray componentsArr = obj.createNestedArray("components");
// status variable for skipping loop
bool skipLoop = true;
// Loop through the JSON object and add the data to the "components" array
for (JsonPair pair : root)
{
// If first loop skip the following
if(skipLoop == false)
{
// Get the name of the top-level keys
String keyName = pair.key().c_str();
// Get the value of the top-level keys
JsonObject obj = pair.value().as<JsonObject>();
// Loop through the JSON object that was the top-level value
for (JsonPair objPair : obj)
{
// Get the name of the low-level keys
String objKeyName = objPair.key().c_str();
// Get the value of the low-level keys
String objValue = objPair.value().as<String>();
// Combine the nane of the top-level keys and low-level keys
String combinedKeyName = keyName + ": " + objKeyName;
// Set the dataUnit based on the combinedKeyName
String dataUnit;
if (combinedKeyName.indexOf("H") != -1 || combinedKeyName.indexOf("M") != -1)
{
dataUnit = "%";
}
else if (combinedKeyName.indexOf("T") != -1)
{
dataUnit = "°C";
}
else if (combinedKeyName.indexOf("R") != -1)
{
dataUnit = " ";
}
// Rplace key names with the expand abbriviation of key names
combinedKeyName.replace("N","Node");
combinedKeyName.replace("S","Soil ");
combinedKeyName.replace("A","Air ");
combinedKeyName.replace("T","Temperature");
combinedKeyName.replace("H","Humidity");
combinedKeyName.replace("M","Moisture");
combinedKeyName.replace("R","Relay");
// Add a new object to the "components" array for each iteration of the loop
JsonObject componentObj = componentsArr.createNestedObject();
componentObj["dataName"] = combinedKeyName;
componentObj["dataValue"] = objValue;
componentObj["dataUnit"] = dataUnit;
}
}
// Turn off skip
skipLoop = false;
}
// Get pointers to the arrays in each document
JsonArray arr1 = doc1[0]["components"];
JsonArray arr2 = componentsArr;
// Iterate through each object in the second JSON array
for (JsonObject obj2 : arr2)
{
// Get the value of the "dataName" key
String dataName2 = obj2["dataName"].as<String>();
bool found = false;
// Iterate through each object in the first JSON array
for (JsonObject obj1 : arr1)
{
// Get the value of the "dataName" key
String dataName1 = obj1["dataName"].as<String>();
// Check if the "dataName" values match
if (dataName1.equals(dataName2))
{
// If they match, update the first object with the data from the second
obj1["dataValue"] = obj2["dataValue"];
obj1["dataUnit"] = obj2["dataUnit"];
found = true;
break;
}
}
// If the "dataName" value wasn't found in the first array, add the second object to the first
if (!found)
{
JsonObject newObj = doc1[0]["components"].createNestedObject();
newObj["dataName"] = obj2["dataName"];
newObj["dataValue"] = obj2["dataValue"];
newObj["dataUnit"] = obj2["dataUnit"];
}
}
// Iterate through each object in the first JSON array
for (JsonObject obj1 : arr1)
{
bool found = false;
// Get the value of the "dataName" key
String dataName1 = obj1["dataName"].as<String>();
// Iterate through each object in the second JSON array
for (JsonObject obj2 : arr2)
{
// Get the value of the "dataName" key
String dataName2 = obj2["dataName"].as<String>();
// Check if the "dataName" values match
if (dataName1.equals(dataName2))
{
found = true;
break;
}
}
// If the "dataName" value wasn't found in the second array, set "nan" and " " values
if (!found)
{
// Loop through each key in the first JSON object
for (const auto& kvp : docP.as<JsonObject>())
{
String key = kvp.key().c_str();
// Check if the key exists in the second JSON object
if (doc2.containsKey(key))
{
// If the value is empty, replace it with "nan"
String value = doc2[key].as<String>();
if (value.equals("{}"))
{
obj1["dataValue"] = "nan";
obj1["dataUnit"] = " ";
}
}
}
}
}
obj["components"] = doc1[0]["components"];
// Serialize the JSON document into a string
serializeJson(arrDoc, output);
// If debug is true do the following
if(debug)
{
// Print the function name
Serial.println(" Function \"getServerPayload\":");
Serial.println();
// Print the JSON string to the serial monitor
Serial.println(output);
Serial.println("................................................................................................." );
}
return output;
}
String compareJSONObjects(String& obj1Str, String& obj2Str) {
StaticJsonDocument<256> obj1Doc;
StaticJsonDocument<256> obj2Doc;
// Deserialize the JSON object strings into JSON objects
deserializeJson(obj1Doc, obj1Str);
deserializeJson(obj2Doc, obj2Str);
JsonObject obj1 = obj1Doc.as<JsonObject>();
JsonObject obj2 = obj2Doc.as<JsonObject>();
// Loop through each key in the second object
for (JsonPair kv2 : obj2) {
const char* key2 = kv2.key().c_str();
// Check if the key exists in the first object
if (obj1.containsKey(key2)) {
// If the key exists in both objects, set the value of the first object to the value of the second object
obj1[key2] = obj2[key2];
} else {
// If the key doesn't exist in the first object, add the key-value pair to the first object
obj1[key2] = obj2[key2];
}
}
// Loop through each key in the first object
for (JsonPair kv1 : obj1) {
const char* key1 = kv1.key().c_str();
// Check if the key exists in the second object
if (!obj2.containsKey(key1)) {
// If the key doesn't exist in the second object, set the value of the first object to "nan"
obj1[key1] = "nan";
}
}
// Serialize the updated first object back into a JSON object string
String output = "";
serializeJson(obj1, output);
return output;
}
String updateJsonData(String string1, String string2) {
// Parse the JSON strings into DynamicJsonDocument objects
DynamicJsonDocument doc1(1024);
deserializeJson(doc1, string1);
DynamicJsonDocument doc2(1024);
deserializeJson(doc2, string2);
// Get the size of each JSON array
int size1 = doc1.size();
int size2 = doc2.size();
// Iterate through each object in the second JSON array
for (int j = 0; j < size2; j++)
{
JsonObject obj2 = doc2[j].as<JsonObject>();
// Get the value of the "dataName" key
String dataName2 = obj2["dataName"].as<String>();
bool found = false;
// Iterate through each object in the first JSON array
for (int i = 0; i < size1; i++)
{
JsonObject obj1 = doc1[i].as<JsonObject>();
// Get the value of the "dataName" key
String dataName1 = obj1["dataName"].as<String>();
// Check if the "dataName" values match
if (dataName1.equals(dataName2))
{
// If they match, update the first object with the data from the second
obj1["dataValue"] = obj2["dataValue"];
obj1["dataUnit"] = obj2["dataUnit"];
found = true;
break;
}
}
// If the "dataName" value wasn't found in the first array, add the second object to the first
if (!found)
{
JsonObject newObj = doc1.createNestedObject();
newObj["dataName"] = obj2["dataName"];
newObj["dataValue"] = obj2["dataValue"];
newObj["dataUnit"] = obj2["dataUnit"];
}
}
// Iterate through each object in the first JSON array
for (int i = 0; i < size1; i++)
{
JsonObject obj1 = doc1[i].as<JsonObject>();
bool found = false;
// Get the value of the "dataName" key
String dataName1 = obj1["dataName"].as<String>();
// Iterate through each object in the second JSON array
for (int j = 0; j < size2; j++)
{
JsonObject obj2 = doc2[j].as<JsonObject>();
// Get the value of the "dataName" key
String dataName2 = obj2["dataName"].as<String>();
// Check if the "dataName" values match
if (dataName1.equals(dataName2))
{
found = true;
break;
}
}
// If the "dataName" value wasn't found in the second array, set "nan" and " " values
if (!found)
{
obj1["dataValue"] = "nan";
obj1["dataUnit"] = " ";
}
}
// Serialize the updated JSON object into a string
String jsonString;
serializeJson(doc1, jsonString);
return jsonString;
}
void setup() {
Serial.begin(9600);
/*
String string1 = "{\"key1\":\"value1\",\"key2\":\"value2\"}";
String string2 = "{\"key2\":\"updatevalue2\",\"key3\":\"newvalue3\"}";
String updated = compareJSONObjects(string1, string2);
*/
/**/
String string1 = R"([{"sn":"SFP001","pk":"78:21:84:7f:64:f4","components":[{"dataName":"Node1: Relay1","dataValue":"0","dataUnit":" "},{"dataName":"Node2: Relay1","dataValue":"1","dataUnit":" "},{"dataName":"Node1: Air Temperature","dataValue":"10","dataUnit":"°C"}]}])";
String string2 = "[{\"dataName\":\"Node2: Relay1\",\"dataValue\":\"updated\",\"dataUnit\":\"updatedUnit\"},{\"dataName\":\"Node3: Relay1\",\"dataValue\":\"added\",\"dataUnit\":\"addedUnit\"}]";
String string3 = "{\"M0\":{\"D\":\">\"},\"N1\":{\"R1\":\"0\",\"T\":\"10\"},\"N2\":{}}";
String string4 = "{\"M0\":{},\"N1\":{},\"N2\":{}}";
// Call the updateJsonData function with the two JSON string arrays
//String updated = updateJsonData(string1, string2);
String updated = getServerPayload("SFP002","79:21:84:7f:64:f4",string1,string4,string3,true);
Serial.println("Before: " + string1);
Serial.println("New updates: " + string3);
Serial.println("After: " + updated);
}
void loop() {
// Do nothing
}