/// <summary> /// Initializes a new instance of the <see cref="MoBackInternal.MatchingQuery"/> class. /// </summary> /// <param name="column"> A column. </param> /// <param name="value"> An object value. </param> public MatchingQuery(string column, object value) { constraints = new SimpleJSONClass(); MoBackValueType type = MoBackInternal.MoBackUtils.ExtractMobackType(ref value); constraints.Add(column, MoBackInternal.MoBackUtils.MoBackTypedObjectToJSON(value, type)); }
/// <summary> /// Modifies the relation for a given row/column. /// </summary> /// <returns>The request object.</returns> /// <param name="tableName">Table name.</param> /// <param name="objectID">Row ID.</param> /// <param name="columnName">Column ID.</param> /// <param name="relationOp">JSON that signifies details of relation operation to MoBack servers.</param> public static MoBackRequest ModifyRelationForGivenRowColumn(string tableName, string objectID, string columnName, SimpleJSONNode relationOp) { SimpleJSONClass opOnColumn = new SimpleJSONClass(); opOnColumn [columnName] = relationOp; /* * Sample uri: https://api.moback.com/objectmgr/api/collections/{tableName}/{objectID} * Sample Json Request Body: * { * "Car": { * "objects": [ * { * "__type": "Pointer", * "objectId": "VqFsguSwp23tC3gF", * "className": "Relations" * },{ * "__type": "Pointer", * "objectId": "VqFsnuSwp23tC3gH", * "className": "Relations" * } * ], * "__op": "addRelation" * } * } */ return(new MoBackRequest(MoBackURLS.TablesDefault + tableName + "/" + objectID, HTTPMethod.PUT, null, opOnColumn.ToString().ToByteArray())); }
/// <summary> /// Return a list of MoBackRow object from the relation JSON /// </summary> /// <returns>The back row from relation JSO.</returns> /// <param name="relationJSON">Relation JSO.</param> public static List <MoBackRow> MoBackRowFromRelationJSON(SimpleJSONNode relationJSON) { SimpleJSONArray nestedArray = relationJSON["value"] as SimpleJSONArray; List <MoBackRow> moBackRows = new List <MoBackRow>(); // If the nested json doesn't have an object type, just return null. // When AchieveRelation without ?include={ColumnName}, it will return a pointer type. for (int i = 0; i < nestedArray.Count; i++) { if (nestedArray[i]["__type"].Value != "object") { if (nestedArray[i]["__type"].Value == "Pointer") { Debug.LogWarning("The response JSON contains Pointer type, not Object type, can't parse this relationJson. Try MoBackRelation.RelationFromMoBackJSON() instead"); return(null); } else { Debug.LogError("Unknown type: " + nestedArray[i]["__type"].Value); return(null); } } SimpleJSONClass jsonObject = nestedArray[i] as SimpleJSONClass; // This will get the MoBackObject exlucde the 2 keys: "__type" and "className". moBackRows.Add(MoBackRow.FromJSON(jsonObject, nestedArray[i]["className"])); } return(moBackRows); }
/// <summary> /// Converts a JSON object to a MobackObject. /// </summary> /// <returns> A MoBackObject. </returns> /// <param name="jsonObject"> A JSON object. </param> public static MoBackObject FromJSON(SimpleJSONClass jsonObject) { MoBackObject mObject = new MoBackObject(); ProcessJsonIntoMoBackObject(mObject, jsonObject); return(mObject); }
/// <summary> /// Converts MoBackObject data to a JSON object for storage. /// </summary> /// <returns>A JSON object.</returns> public override SimpleJSONClass GetJSON() { // Construct a child json object, which is the File type. SimpleJSONClass jsonForUploadFile = new SimpleJSONClass(); jsonForUploadFile["__type"] = "File"; jsonForUploadFile["name"] = Name; jsonForUploadFile["url"] = url; // Final json structure to send to server, to create a new row. SimpleJSONClass jsonStructure = new SimpleJSONClass(); // Add the child json. jsonStructure.Add("FileURL", jsonForUploadFile); // Add other values if any. foreach (KeyValuePair <string, object> item in storeValues) { if (item.Key == "objectId" || item.Key == "createdAt" || item.Key == "updatedAt") { continue; // No need to send auto-populated fields as part of JSON message } SimpleJSONNode node = MoBackUtils.MoBackTypedObjectToJSON(item.Value, columnTypeData[item.Key]); jsonStructure.Add(item.Key, node); } return(jsonStructure); }
/// <summary> /// Converts a JSON object to a MoBackRow object. /// </summary> /// <returns>The JSON date converted to a MoBackRow.</returns> /// <param name="jsonObject">A JSON object.</param> /// <param name="sourceTableID">Source table ID.</param> public static MoBackRow FromJSON(SimpleJSONClass jsonObject, string sourceTableID = null) { MoBackRow mObject = ExtractMetadata(jsonObject, sourceTableID); ProcessJsonIntoMoBackObject(mObject, jsonObject); return(mObject); }
public static MoBackRequest ResetPassword(string userName) { SimpleJSONClass jsonStructure = new SimpleJSONClass(); jsonStructure.Add("userId", userName); byte[] postData = jsonStructure.ToString().ToByteArray(); return(new MoBackRequest(MoBackURLS.ResetPassword, HTTPMethod.POST, null, postData)); }
/// <summary> /// Returns the JSON object. /// </summary> /// <returns>The JSO.</returns> public SimpleJSONClass GetJSON() { SimpleJSONClass jsonObject = new SimpleJSONClass(); jsonObject.Add("__type", "GeoPoint"); jsonObject.Add("lat", Latitude); jsonObject.Add("lon", Longitude); return(jsonObject); }
/// <summary> /// Converts a MoBackPointer to a JSON object for storage. /// </summary> /// <returns> A JSON object. </returns> /// <param name="pointer"> A MoBackPointer object. </param> public static SimpleJSONClass PointerToMoBackJSON(MoBackPointer pointer) { SimpleJSONClass pointerJsonStructure = new SimpleJSONClass(); pointerJsonStructure["__type"] = "Pointer"; pointerJsonStructure["objectId"] = pointer.objectID; pointerJsonStructure["className"] = pointer.tableID; return(pointerJsonStructure); }
/// <summary> /// Converts MoBackObject data to a JSON object for storage. /// </summary> /// <returns> A JSON object. </returns> public virtual SimpleJSONClass GetJSON() { SimpleJSONClass jsonStructure = new SimpleJSONClass(); foreach (KeyValuePair <string, object> item in storeValues) { SimpleJSONNode node = MoBackUtils.MoBackTypedObjectToJSON(item.Value, columnTypeData[item.Key]); jsonStructure.Add(item.Key, node); } return(jsonStructure); }
/// <summary> /// Initializes a new instance of the <see cref="MoBackInternal.ComparisonQuery"/> class. /// </summary> /// <param name="column"> A column.</param> /// <param name="value"> An object value. </param> /// <param name="comparisonOperator"> A comparison operator as a string. </param> public ComparisonQuery(string column, object value, string comparisonOperator) { constraints = new SimpleJSONClass(); SimpleJSONClass constraint = new SimpleJSONClass(); MoBackValueType type = MoBackInternal.MoBackUtils.ExtractMobackType(ref value); constraint.Add(comparisonOperator, MoBackInternal.MoBackUtils.MoBackTypedObjectToJSON(value, type)); constraints.Add(column, constraint); }
/// <summary> /// Find if the JSON class contains any of the specified keywords. /// </summary> /// <returns><c>true</c>, if class contains keywords, <c>false</c> otherwise.</returns> /// <param name="jsonObject"> A JSON object. </param> private bool JsonClassContainsKeywords(SimpleJSONClass jsonObject) { foreach (KeyValuePair <string, SimpleJSONNode> jsonNode in jsonObject.dict) { if (NameIsKeyword(jsonNode.Key)) { return(true); } } return(false); }
/// <summary> /// Updates the user info. /// </summary> /// <returns>A MoBackRequest with a MoBackUser type.</returns> public MoBackRequest UpdateUserInfo() { if (!IsLoggedIn) { Debug.LogError("This current user hasn't been logged in yet"); return(null); } SimpleJSONClass jsonStructure = GetJSON(); return(new MoBackRequest(MoBackURLS.User, HTTPMethod.PUT, null, jsonStructure.ToString().ToByteArray())); }
/// <summary> /// Initializes a new instance of the <see cref="MoBackInternal.CompoundQuery"/> class. /// </summary> /// <param name="compoundOperator"> A compound operator. </param> /// <param name="queriesToCompound"> An array of queries to compound. </param> public CompoundQuery(string compoundOperator, params Query[] queriesToCompound) { constraints = new SimpleJSONClass(); SimpleJSONArray constraintValues = new SimpleJSONArray(); foreach (Query query in queriesToCompound) { constraintValues.Add(query.constraints); } constraints.Add(compoundOperator, constraintValues); }
/// <summary> /// Sends the invitation. /// </summary> /// <returns>A MoBackRequest with a MoBackUser type.</returns> /// <param name="emailAddress">Email address.</param> public MoBackRequest SendInvitation(string emailAddress) { if (string.IsNullOrEmpty(emailAddress)) { Debug.LogError("Invalid email address"); return(null); } SimpleJSONClass jsonStructure = new SimpleJSONClass(); jsonStructure.Add("inviteeId", emailAddress); byte[] postData = jsonStructure.ToString().ToByteArray(); return(new MoBackRequest(MoBackURLS.Invitation, HTTPMethod.POST, null, postData)); }
public static SimpleJSONClass DateToMobackFormatJSON(DateTime date) { SimpleJSONClass dateJsonStructure = new SimpleJSONClass(); dateJsonStructure ["__type"] = "Date"; dateJsonStructure ["iso"] = String.Format("{0:0000}-{1:00}-{2:00}T{3:00}:{4:00}:{5:00}.{6:000}Z", date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Millisecond); return(dateJsonStructure); }
/// <summary> /// Converts MoBackObject data to a JSON object for storage. /// </summary> /// <returns>A JSON object.</returns> public override SimpleJSONClass GetJSON() { SimpleJSONClass jsonStructure = new SimpleJSONClass(); foreach (KeyValuePair <string, object> item in storeValues) { if (item.Key == "objectId" || item.Key == "createdAt" || item.Key == "updatedAt") { continue; // No need to send auto-populated fields as part of JSON message } SimpleJSONNode node = MoBackUtils.MoBackTypedObjectToJSON(item.Value, columnTypeData[item.Key]); jsonStructure.Add(item.Key, node); } return(jsonStructure); }
/// <summary> /// MoBack JSON from relation. Of dubious usefulness because uploading and updating relations directly is presently forbidden. /// </summary> /// <returns>The moback JSON representing the relation.</returns> /// <param name="relation">Relation.</param> public static SimpleJSONNode MoBackJSONFromRelation(MoBackRelation relation) { SimpleJSONClass relationJSON = new SimpleJSONClass(); relationJSON ["__type"] = "Pointer"; SimpleJSONArray pointersJSON = new SimpleJSONArray(); for (int i = 0; i < relation._pointers.Count; i++) { pointersJSON.Add(MoBackPointer.PointerToMoBackJSON(relation._pointers[i])); } relationJSON ["value"] = pointersJSON; return(relationJSON); }
/// <summary> /// Gets JSON the server expects for an remove relation operation, that removes the supplied list of pointers to some relation. /// </summary> /// <returns>The remove operation as mo back JSO.</returns> /// <param name="pointersToRemove">Pointers to add.</param> public static SimpleJSONClass RelationRemoveOpAsMoBackJSON(MoBackPointer[] pointersToRemove) { SimpleJSONClass relationOpJsonStructure = new SimpleJSONClass(); relationOpJsonStructure ["__op"] = "removeRelation"; SimpleJSONArray pointers = new SimpleJSONArray(); for (int i = 0; i < pointersToRemove.Length; i++) { pointers.Add(MoBackPointer.PointerToMoBackJSON(pointersToRemove[i])); } relationOpJsonStructure ["objects"] = pointers; return(relationOpJsonStructure); }
/// <summary> /// Initializes a new instance of the <see cref="MoBackInternal.ComparisonQuery"/> class. /// </summary> /// <param name="column"> A column.</param> /// <param name="values"> An array object values. </param> /// <param name="comparisonOperator"> A comparison operator as a string. </param> public ComparisonQuery(string column, object[] values, string comparisonOperator) { constraints = new SimpleJSONClass(); SimpleJSONClass constraint = new SimpleJSONClass(); SimpleJSONArray constraintValues = new SimpleJSONArray(); for (int i = 0; i < values.Length; i++) { object value = values[i]; MoBackValueType type = MoBackInternal.MoBackUtils.ExtractMobackType(ref value); constraintValues.Add(MoBackInternal.MoBackUtils.MoBackTypedObjectToJSON(value, type)); } constraint.Add(comparisonOperator, constraintValues); constraints.Add(column, constraint); }
/// <summary> /// Deletes the column. /// </summary> /// <returns>Returns the status of the request.</returns> /// <param name="columnName">Column name.</param> public MoBackRequest DeleteColumn(string columnName) { SimpleJSONClass columnOp = new SimpleJSONClass(); columnOp.Add("__op", "Delete"); SimpleJSONClass columnDataHolder = new SimpleJSONClass(); columnDataHolder.Add(columnName, columnOp); /* * Sample uri: https://api.moback.com/objectmgr/api/schema/{tableName}/ * Sample Json Request Body: * { * "Over21" : {"__op" : "Delete"} * } */ return(new MoBackRequest(MoBackURLS.TablesSpecial + table.TableName, HTTPMethod.PUT, null, columnDataHolder.ToString().ToByteArray())); }
/// <summary> /// Deletes the multiple ojbects. /// </summary> /// <returns>A MoBackRequest.</returns> /// <param name="objectsToDelete">Objects to delete.</param> public MoBackRequest DeleteMultipleOjbects(List <MoBackRow> objectsToDelete) { string uri = MoBackURLS.BatchDelete + table.TableName; SimpleJSONArray jsonArray = new SimpleJSONArray(); SimpleJSONClass jsonBody = new SimpleJSONClass(); foreach (MoBackRow item in objectsToDelete) { jsonArray.Add(MoBackUtils.MoBackTypedObjectToJSON(item.ObjectId, MoBackValueType.String)); } jsonBody.Add("objectIds", jsonArray); byte[] bytes = jsonBody.ToString().ToByteArray(); MoBackRequest.ResponseProcessor deleteCallBack = (SimpleJSONNode responseJson) => { SimpleJSONArray responseArray = responseJson["deletedObjectIds"].AsArray; Debug.Log(responseArray.ToString()); foreach (SimpleJSONNode item in responseArray) { MoBackRow deletedRow = objectsToDelete.Find(row => row.ObjectId == item.Value); if (deletedRow != null) { deletedRow.ResetMetaData(null); } else { Debug.Log("Can't find row"); } } }; /* * Sample uri: https://api.moback.com/objectmgr/api/collections/batch/delete/{tableName} * Sample Json Request Body: * { * "objectIds" : ["Vp6pfOSwp23tC3IN", "Vp6ZnOSwp23tC3Hv"] * } */ return(new MoBackRequest(deleteCallBack, uri, HTTPMethod.POST, null, bytes)); }
/// <summary> /// Processes a JSON object into a MoBackObject. /// </summary> /// <param name="mObject"> A MoBackObject to process. </param> /// <param name="jsonObject"> A JSON object. </param> protected static void ProcessJsonIntoMoBackObject(MoBackObject mObject, SimpleJSONClass jsonObject) { foreach (KeyValuePair <string, SimpleJSONNode> entry in jsonObject.dict) { // These 2 values are in Relation array values when RetrieveRelation with ?include={ColumnName} // key == success is for BatchProcessing, after saving/updating, success is auto generated and return in json. if (entry.Key == "__type" || entry.Key == "className" || entry.Key == "success") { continue; } MoBackValueType moBackType; object data = MoBackUtils.MoBackTypedObjectFromJSON(entry.Value, out moBackType); // This should always be equivalent to calling SetValue() with the appropriate type; if SetValue() functions are refactored then so too should this, and vice-versa. mObject.SetColumnType(entry.Key, moBackType); mObject.storeValues[entry.Key] = data; } }
/// <summary> /// Creates the column. /// </summary> /// <returns>Returns the status of the request.</returns> /// <param name="columnName">Column name.</param> /// <param name="columnType">Column type.</param> public MoBackRequest CreateColumn(string columnName, MoBackValueType columnType) { SimpleJSONClass columnTypeSpecifier = new SimpleJSONClass(); // TODO: check if any of these type-names don't fit the moback spec. According to REST api reference they should be... columnTypeSpecifier.Add("__type", columnTypeSpecifier.ToString()); SimpleJSONClass columnDataHolder = new SimpleJSONClass(); columnDataHolder.Add(columnName, columnTypeSpecifier); /* * Sample uri: https://api.moback.com/objectmgr/api/schema/{tableName}/ * Sample Json Request Body: * { * "FavoriteFood" : {"__type" : "string"} * } */ return(new MoBackRequest(MoBackURLS.TablesSpecial + table.TableName, HTTPMethod.PUT, null, columnDataHolder.ToString().ToByteArray())); }
/// <summary> /// Check for any MoBack reserved columns, and then process them. /// </summary> /// <returns>The metadata.</returns> /// <param name="jsonObject">A JSON object.</param> /// <param name="sourceTableID">Source table ID.</param> private static MoBackRow ExtractMetadata(SimpleJSONClass jsonObject, string sourceTableID) { string objIO = null; DateTime createdOn = default(DateTime); DateTime updatedOn = default(DateTime); if (jsonObject.dict.ContainsKey("objectId")) { objIO = jsonObject["objectId"]; } if (jsonObject.dict.ContainsKey("createdAt")) { createdOn = MoBackDate.DateFromString(jsonObject["createdAt"]); } if (jsonObject.dict.ContainsKey("updatedAt")) { updatedOn = MoBackDate.DateFromString(jsonObject["updatedAt"]); } return(new MoBackRow(sourceTableID, objIO, createdOn, updatedOn)); }
/// <summary> /// Gets the user info. /// </summary> /// <returns>A MoBackRequest with a MoBackUser type.</returns> public MoBackRequest GetUserInfo() { // If there is not sessiontoken means user hasn't logged in yet, just exit. if (!IsLoggedIn) { Debug.LogError("There is no current login user."); return(null); } MoBackRequest.ResponseProcessor GetCurrentUserInfoProcessor = (SimpleJSONNode jsonObject) => { SimpleJSONClass userInfoJson = jsonObject["user"] as SimpleJSONClass; foreach (KeyValuePair <string, SimpleJSONNode> entry in userInfoJson.dict) { // we stored these outside of storeValues. if (entry.Key == "userId" || entry.Key == "createdAt" || entry.Key == "updatedAt" || entry.Key == "objectId") { continue; } MoBackValueType moBackType; object data = MoBackUtils.MoBackTypedObjectFromJSON(entry.Value, out moBackType); // This should always be equivalent to calling SetValue() with the appropriate type; if SetValue() functions are refactored then so too should this, and vice-versa. this.SetColumnType(entry.Key, moBackType); this.storeValues[entry.Key] = data; } UserName = userInfoJson["userId"]; ObjectId = userInfoJson["objectId"]; CreatedDate = MoBackDate.DateFromString(userInfoJson["createdAt"]); UpdatedDate = MoBackDate.DateFromString(userInfoJson["updatedAt"]); }; return(new MoBackRequest(GetCurrentUserInfoProcessor, MoBackURLS.User, HTTPMethod.GET, null, null)); }
/// <summary> /// Login the specified userName and password. /// </summary> /// <param name="userName">User name.</param> /// <param name="password">Password.</param> /// <returns>A MoBackRequest with a MoBackUser type.</returns> public MoBackRequest Login() { SimpleJSONClass jsonStructure = new SimpleJSONClass(); jsonStructure.Add("userId", UserName); jsonStructure.Add("password", Password); byte[] postData = jsonStructure.ToString().ToByteArray(); MoBackRequest.ResponseProcessor LoginProcessor = (SimpleJSONNode jsonObject) => { string ssotoken = jsonObject["ssotoken"]; if (string.IsNullOrEmpty(ssotoken)) { IsLoggedIn = false; } else { IsLoggedIn = true; MoBack.MoBackAppSettings.SessionToken = ssotoken; } }; return(new MoBackRequest(LoginProcessor, MoBackURLS.Login, HTTPMethod.POST, null, postData)); }
public static object MoBackTypedObjectFromJSON(SimpleJSONNode node, out MoBackValueType dataType) { if (MoBackAppSettings.doublePrecisionFloatingPoint && node.valueType == typeof(double)) { dataType = MoBackValueType.Number; return(new MoBackNumber(node.AsDouble)); } else if (!MoBackAppSettings.doublePrecisionFloatingPoint && node.valueType == typeof(float)) { dataType = MoBackValueType.Number; return(new MoBackNumber(node.AsFloat)); } else if (node.valueType == typeof(int)) { dataType = MoBackValueType.Number; return(new MoBackNumber(node.AsInt)); } else if (node.valueType == typeof(bool)) { dataType = MoBackValueType.Boolean; return(node.AsBool); } else if (node.valueType == typeof(string)) { dataType = MoBackValueType.String; return(node.Value); } else if (node.valueType == typeof(SimpleJSONClass)) { SimpleJSONClass nestedClass = (SimpleJSONClass)node; if (nestedClass.dict.ContainsKey("__type")) { //is a special type, treat accordingly switch (nestedClass["__type"].Value) { case "Date": dataType = MoBackValueType.Date; return(MoBackDate.DateFromMoBackJSON(node)); case "Pointer": dataType = MoBackValueType.Pointer; return(MoBackPointer.PointerFromMoBackJSON(node)); case "Relation": dataType = MoBackValueType.Relation; return(MoBackRelation.RelationFromMoBackJSON(node)); case "File": dataType = MoBackValueType.File; return(MoBackFile.FromJSON(node)); default: //not familiar with this special type; fall back to parsing as regular object if (MoBack.MoBackAppSettings.loggingLevel >= MoBack.MoBackAppSettings.LoggingLevel.WARNINGS) { Debug.LogWarning("Unrecognized MoBack reserved type '" + nestedClass["__type"] + "'."); } dataType = MoBackValueType.MoBackObject; return(MoBackObject.FromJSON(nestedClass)); } } else { dataType = MoBackValueType.MoBackObject; return(MoBackObject.FromJSON(nestedClass)); } } else if (node.valueType == typeof(SimpleJSONArray)) { dataType = MoBackValueType.Array; return(MoBackArray.FromJSON((SimpleJSONArray)node)); } throw new ArgumentException("JSON data type not supported in some manner.", "SimpleJsonNode node"); }
/// <summary> /// Merge queries, potentially recursively. /// </summary> /// <param name="first">First query. This also contains the merged result after the merge.</param> /// <param name="second">Second query.</param> private void MergeQueries(SimpleJSONClass first, SimpleJSONClass second) { // Needs to merge various things correctly. For a (non-encompassing) example of the problem, take: // {"playerName":"Sean Plott","cheatMode":{"thisIsanObject":true}} // {"playerName":{"$exists":true}} // {"cheatMode":{"note":"ThisIsPartOfAnObjectNotAConstraint", "cheat":"noSecretCows"}} // {"rank":{"$gte":1,"$lte":10}} // {"rank":{"$in":[2,3,6]}} // {"$and":[{"StudentName":”Mark Lee”},{"standard":4}]} // Should turn into: // {"playerName":"Sean Plott","cheatMode":{"note":"ThisIsPartOfAnObjectNotAConstraint", "cheat":"noSecretCows"}, "rank":{"$gte":1,"$lte":10,"$in":[2,3,6]}, // "$and":[{"StudentName":”Mark Lee”},{"standard":4}]} // Approach: // 0.When keywords don't conflict, just add both // 1.Two objects containing $keywords should be merged, following these rules recursively (relevantly, constants override constants, but arrays with $names are merged) // 2.Arrays with $names should be merged, by appending second array after first // 3.For two constant values (strings, ints, etc), in the case of a conflict the second value should override the first. // ^Objects not containing $keywords and arrays without $names should be treated as constants // 5.When a conflict is not otherwise covered by these rules, just use the second of the two values // 6.Consider implementing in the future: Between an object containing $keywords and a constant match being provied, pick the constant match // (because an exact match effectively supercedes all constraints (except maybe mutually conflicting constraints which should axiomatically return nothing... // but not sure how that should be dealt with anyway? life would be simpler if we had an $eq operator exposed) foreach (KeyValuePair <string, SimpleJSONNode> node in second.dict) { if (first.dict.ContainsKey(node.Key)) { SimpleJSONNode firstNode = first[node.Key]; SimpleJSONNode secondNode = node.Value; System.Type firstType = firstNode.valueType; System.Type secondType = secondNode.valueType; if (firstType == typeof(SimpleJSONClass) || secondType == typeof(SimpleJSONClass)) { bool firstIsClassContainingKeywords = firstType == typeof(SimpleJSONClass) && JsonClassContainsKeywords((SimpleJSONClass)firstNode); bool secondIsClassContainingKeywords = secondType == typeof(SimpleJSONClass) && JsonClassContainsKeywords((SimpleJSONClass)secondNode); if (firstIsClassContainingKeywords && secondIsClassContainingKeywords) { // Merge recursively SimpleJSONClass firstObject = (SimpleJSONClass)firstNode; SimpleJSONClass secondObject = (SimpleJSONClass)secondNode; MergeQueries(firstObject, secondObject); } else { // Newer value takes precedence first.Add(node.Key, node.Value); } } else if (firstType == typeof(SimpleJSONArray) && secondType == typeof(SimpleJSONArray) && NameIsKeyword(node.Key)) { // Merge arrays SimpleJSONArray firstArray = (SimpleJSONArray)firstNode; SimpleJSONArray secondArray = (SimpleJSONArray)secondNode; for (int i = 0; i < secondArray.Count; i++) { firstArray.Add(secondArray[i]); } } else { // Newer value takes precedence first.Add(node.Key, node.Value); } } else { // No conflict, just add first.Add(node.Key, node.Value); } } }
/// <summary> /// Saves multiple objects with one single call to server. /// </summary> /// <returns>The MobackRequest.</returns> /// <param name="rowsToSave">MoBack Rows need to save.</param> public MoBackRequest SaveMultipleObjects(List <MoBackRow> rowsToSave) { string uri = MoBackURLS.Batch + table.TableName; SimpleJSONArray jsonArray = new SimpleJSONArray(); SimpleJSONClass jsonStructure = new SimpleJSONClass(); for (int i = 0; i < rowsToSave.Count; i++) { SimpleJSONClass jsonToSave = rowsToSave[i].GetJSON(); if (rowsToSave[i].ObjectId != null) { jsonToSave.Add("objectId", rowsToSave[i].ObjectId); } jsonArray.Add(jsonToSave); } jsonStructure.Add("objects", jsonArray); Debug.Log(jsonStructure.ToString()); byte[] bytes = jsonStructure.ToString().ToByteArray(); // Construct a callback to update all rowsToSave. MoBackRequest.ResponseProcessor objUpdater = (SimpleJSONNode responseJson) => { SimpleJSONClass allObjectsInJsonFormat = responseJson["batchResponse"].AsObject; // The response should have the same amount as of the request body. if (allObjectsInJsonFormat.Count != rowsToSave.Count) { Debug.LogError(string.Format("Response objects count: {0}. Request objects count: {1}", allObjectsInJsonFormat.Count, rowsToSave.Count)); Debug.LogError("Response doesn't have the same object as Request Body. Something wrong!"); return; } for (int i = 0; i < rowsToSave.Count; i++) { SimpleJSONClass jsonAtCurrentIndex = allObjectsInJsonFormat[i] as SimpleJSONClass; if (!jsonAtCurrentIndex["success"].AsBool) { Debug.LogError("Unable to save: " + jsonAtCurrentIndex["objectId"]); continue; } if (!string.IsNullOrEmpty(jsonAtCurrentIndex["createdAt"].ToString())) { string objectId = jsonAtCurrentIndex["objectId"]; DateTime createdTime = MoBackDate.DateFromString(jsonAtCurrentIndex["createdAt"]); rowsToSave[i].UpdateAfterSave(objectId, createdTime, createdTime); } else if (!string.IsNullOrEmpty(jsonAtCurrentIndex["updatedAt"].ToString())) { string objectId = jsonAtCurrentIndex["objectId"]; DateTime updateTime = MoBackDate.DateFromString(jsonAtCurrentIndex["updatedAt"]); rowsToSave[i].UpdateAfterSave(objectId, null, updateTime); } } }; /* * Sample uri: https://api.moback.com/objectmgr/api/collections/batch/{tableName} * Sample Json Request Body: * { * "objects" : [{ "Name" : "Joe", "FavoriteFood" : ["pizza", "fried eggs", "ham sandwich"]}] * } */ return(new MoBackRequest(objUpdater, uri, HTTPMethod.POST, null, bytes)); }