/// <summary> /// Creates a MoBackRelation object from JSON returned from server. /// </summary> /// <returns>The relation.</returns> /// <param name="relationJSON">Relation in JSON form, from server.</param> public static MoBackRelation RelationFromMoBackJSON(SimpleJSONNode relationJSON) { MoBackRelation relation = new MoBackRelation(); SimpleJSONArray pointersJSON = relationJSON ["value"].AsArray; for (int i = 0; i < pointersJSON.Count; i++) { // If the nested json doesn't have a pointer type, just return null. // When AchieveRelation with ?include={ColumnName}, it will return an object type. if (pointersJSON[i]["__type"].Value != "Pointer") { if (pointersJSON[i]["__type"].Value == "object") { Debug.LogWarning("The response JSON contains Object type, not Pointer type, can't parse this relationJson. Try MoBackRelation.MoBackRowFromRelationJSON() instead"); return(null); } else { Debug.LogError("Unknown type: " + pointersJSON[i]["__type"].Value); return(null); } } relation._pointers.Add(MoBackPointer.PointerFromMoBackJSON(pointersJSON[i])); } return(relation); }
/// <summary> /// Converts latitude and longitude data from a JSON object to a double value type. /// </summary> /// <returns>The JSO.</returns> /// <param name="node">Node.</param> public static MoBackGeoPoint FromJSON(SimpleJSONNode node) { double lat = node["lat"].AsDouble; double lon = node["lon"].AsDouble; return(new MoBackGeoPoint(lat, lon)); }
/// <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 MoBackPointer object. /// </summary> /// <returns> A MoBackPointer object. </returns> /// <param name="pointerJSON"> A JSON object. </param> public static MoBackPointer PointerFromMoBackJSON(SimpleJSONNode pointerJSON) { string objID = pointerJSON["objectId"]; string table = pointerJSON["className"]; return(new MoBackPointer(objID, table)); }
/// <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> /// 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> /// Froms the JSO. /// </summary> /// <returns>The JSO.</returns> /// <param name="jsonObject">Json object.</param> public static MoBackFile FromJSON(SimpleJSONNode jsonObject) { MoBackFile fileHolder = new MoBackFile(); fileHolder.Name = jsonObject["name"]; fileHolder.url = jsonObject["url"]; return(fileHolder); }
public void ResetMetaData(SimpleJSONNode rawResponse) { Debug.Log("Reset meta data"); // Reset default meta values. ObjectId = null; CreatedDate = null; UpdatedDate = null; }
/// <summary> /// Requests the result callback. /// </summary> /// <param name="rawMessage"> The raw message. </param> /// <param name="jsonIfAny"> A JSON object, if any. </param> protected virtual void RequestResultCallback(string rawMessage, SimpleJSONNode jsonIfAny) { if (responseProcessor != null) { responseProcessor(jsonIfAny); } message = rawMessage; currentRun = null; State = RequestState.COMPLETED; }
/// <summary> /// Converts MobackValueType objects into JSON objects. /// </summary> /// <returns> An simple JSON array of JSON objects. </returns> public SimpleJSONArray GetJSON() { SimpleJSONArray jsonArray = new SimpleJSONArray(); for (int i = 0; i < objects.Count; i++) { SimpleJSONNode node = MoBackUtils.MoBackTypedObjectToJSON(objects[i], objectTypes[i]); jsonArray.Add(node); } return(jsonArray); }
/// <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> /// Deletes the file processor. /// </summary> /// <param name="responseJson">Response json.</param> private void DeleteFileProcessor(SimpleJSONNode responseJson) { string responseCode = responseJson["code"]; if (responseCode == "1000") { Debug.Log("Reset MoBackFile object"); // delete request success. Reset the local version of the MoBackFile. this.url = null; this.Name = null; this.data = null; } }
/// <summary> /// Gets the objects processor. /// </summary> /// <returns>A list of objects of the MoBackRow type converted from a JSON object.</returns> /// <param name="jsonObject">JSON object.</param> private List <MoBackRow> GetObjects_processor(SimpleJSONNode jsonObject) { List <MoBackRow> objects = new List <MoBackRow>(); // TODO: this doesn't work. Need to double check later. SimpleJSONArray results = jsonObject["results"].AsArray; for (int i = 0; i < results.Count; i++) { objects.Add(MoBackRow.FromJSON(results[i] as SimpleJSONClass, table.TableName)); } return(objects); }
/// <summary> /// Gets all relation objects. /// </summary> /// <returns>The all relation objects.</returns> /// <param name="tableName">Table name.</param> /// <param name="objectID">Object I.</param> /// <param name="columnName">Column name.</param> public static MoBackRequest <List <MoBackRow> > GetAllRelationObjects(string tableName, string objectID, string columnName) { MoBackRequest <List <MoBackRow> > .ResponseProcessor getAllRelationObjectsProcessor = (SimpleJSONNode responseJson) => { SimpleJSONNode relationJson = responseJson[columnName]; List <MoBackRow> moBackObjects = MoBackRelation.MoBackRowFromRelationJSON(relationJson); return(moBackObjects); }; /* * Sample uri: https://api.moback.com/objectmgr/api/collections/{tableName}/{objectID}?include={columnName} */ return(new MoBackRequest <List <MoBackRow> >(getAllRelationObjectsProcessor, MoBackURLS.TablesDefault + tableName + "/" + objectID + string.Format("?include={0}", columnName), HTTPMethod.GET)); }
/// <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> /// Gets all relation pointers. /// </summary> /// <returns>The all relation pointers.</returns> /// <param name="tableName">Table name.</param> /// <param name="objectID">Object I.</param> /// <param name="columnName">Column name.</param> public static MoBackRequest <List <MoBackPointer> > GetAllRelationPointers(string tableName, string objectID, string columnName) { MoBackRequest <List <MoBackPointer> > .ResponseProcessor getAllRelationPointersProcessor = (SimpleJSONNode responseJson) => { SimpleJSONNode relationJson = responseJson[columnName]; MoBackRelation moBackRelation = MoBackRelation.RelationFromMoBackJSON(relationJson); if (moBackRelation != null) { return(moBackRelation.pointers.ToList()); } return(null); }; /* * Sample uri: https://api.moback.com/objectmgr/api/collections/{tableName}/{objectID} */ return(new MoBackRequest <List <MoBackPointer> >(getAllRelationPointersProcessor, MoBackURLS.TablesDefault + tableName + "/" + objectID, HTTPMethod.GET)); }
/// <summary> /// Runs the request. /// </summary> /// <param name="url"> The url to send a request to. </param> /// <param name="methodType"> A method type. </param> /// <param name="errorHandler"> A callback to handle errors. </param> /// <param name="callback"> A callback to handle a succesful request. Null by default. </param> /// <param name="query"> A set of query parameters. Null by default. </param> /// <param name="body"> A byte array. </param> /// <param name="contentType"> A content type of this request. If left the value null, the contentType will be "application/json". </param> public static void RunRequest(string url, HTTPMethod methodType, RequestErrorCallback errorHandler, RequestResultCallback callback = null, MoBackRequestParameters query = null, byte[] body = null, string contentType = null) { WebRequest request; if (query != null) { request = WebRequest.Create(url + query); } else { request = WebRequest.Create(url); } if (MoBack.MoBackAppSettings.loggingLevel >= MoBackAppSettings.LoggingLevel.VERBOSE) { Debug.Log(request.RequestUri.AbsoluteUri); } // Insert keys WebHeaderCollection collection = new WebHeaderCollection(); collection.Add("X-Moback-Application-Key", MoBack.MoBackAppSettings.ApplicationID); collection.Add("X-Moback-Environment-Key", MoBack.MoBackAppSettings.EnvironmentKey); // Set session token if there is one. if (!string.IsNullOrEmpty(MoBack.MoBackAppSettings.SessionToken)) { collection.Add("X-Moback-SessionToken-Key", MoBack.MoBackAppSettings.SessionToken); } request.Headers = collection; // Specify request as GET, POST, PUT, or DELETE request.Method = methodType.ToString(); if (string.IsNullOrEmpty(contentType)) { request.ContentType = "application/json"; } else { request.ContentType = contentType; } // Specify request content length request.ContentLength = body == null ? 0 : body.Length; string responseFromServer = String.Empty; #if UNITY_ANDROID && !UNITY_EDITOR ServicePointManager.ServerCertificateValidationCallback = SSLValidator.Validator; #elif UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && !UNITY_EDITOR_OSX) ServicePointManager.ServerCertificateValidationCallback = Validator; #endif try { // Open a stream and send the request to the remote server Stream dataStream = null; if (body != null) { dataStream = request.GetRequestStream(); dataStream.Write(body, 0, body.Length); dataStream.Close(); } // Complete the request, wait for and accept any response WebResponse response = request.GetResponse(); // Process response if (MoBackAppSettings.loggingLevel >= MoBackAppSettings.LoggingLevel.VERBOSE) { Debug.Log(((HttpWebResponse)response).StatusDescription); } dataStream = response.GetResponseStream(); StreamReader reader = new StreamReader(dataStream); responseFromServer = reader.ReadToEnd(); // Debug.Log("the json is "+responseFromServer.ToString()); // Close all streams reader.Close(); response.Close(); } catch (WebException webException) { HttpWebResponse errorResponse = webException.Response as HttpWebResponse; if (errorResponse != null) { if (MoBackAppSettings.loggingLevel >= MoBackAppSettings.LoggingLevel.WARNINGS) { Debug.LogWarning(string.Format("Network Request Error {0}: {1}.\nFull Exception: {2}", (int)errorResponse.StatusCode, errorResponse.StatusCode.ToString(), MoBackError.FormatException(webException))); } errorHandler(webException, webException.Status, errorResponse.StatusCode, webException.Message); } else { if (MoBackAppSettings.loggingLevel >= MoBackAppSettings.LoggingLevel.WARNINGS) { Debug.LogWarning(string.Format("Network Request Failed with message {0}.\nFull exception: {1}", webException.Message, MoBackError.FormatException(webException))); } errorHandler(webException, webException.Status, null, webException.Message); } return; } if (MoBackAppSettings.loggingLevel >= MoBackAppSettings.LoggingLevel.VERBOSE) { Debug.Log(responseFromServer); } if (callback != null) { SimpleJSONNode responseAsJSON = SimpleJSONNode.Parse(responseFromServer); callback(responseFromServer, responseAsJSON); } }
/// <summary> /// A callback when UploadFile request is completed. /// </summary> /// <param name="responseJson">Response json.</param> private void UploadFileProcessor(SimpleJSONNode responseJson) { this.Name = responseJson["name"]; this.url = responseJson["url"]; }
public static DateTime DateFromMoBackJSON(SimpleJSONNode dateWrapper) { return(DateFromString(dateWrapper["iso"])); }
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"); }
// Basically the callbacks for processing results, with particular regards to the current table #region JSONResponseProcessors /// <summary> /// Fetch the column descriptions_processor. /// </summary> /// <param name="jsonObject">JSON object.</param> private void FetchColumnDescriptions_processor(SimpleJSONNode jsonObject) { // Stub }
/// <summary> /// Gets the object processor. /// </summary> /// <returns>The a MoBackRow converted from a JSON object.</returns> /// <param name="jsonObject">A JSON object.</param> private MoBackRow GetObject_processor(SimpleJSONNode jsonObject) { return(MoBackRow.FromJSON(jsonObject as SimpleJSONClass, table.TableName)); }
/// <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); } } }