chore: 替换 json 解析实现

oneRain 2019-08-06 12:16:17 +08:00
parent ca3b19311c
commit 70b3a37fe3
24 changed files with 200 additions and 102 deletions

View File

@ -0,0 +1,61 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using LeanCloud.Storage.Internal;
namespace LeanCloudTests {
public class JsonTest {
[Test]
public void Deserialize() {
// 对象类型
var obj = JsonConvert.DeserializeObject("{\"id\": 123}");
TestContext.Out.WriteLine(obj.GetType());
Assert.AreEqual(obj.GetType(), typeof(JObject));
// 数组类型
var arr = JsonConvert.DeserializeObject("[1, 2, 3]");
TestContext.Out.WriteLine(arr.GetType());
Assert.AreEqual(arr.GetType(), typeof(JArray));
try {
// null
var na = JsonConvert.DeserializeObject(null);
TestContext.Out.WriteLine(na.GetType());
} catch (ArgumentNullException) {
}
Assert.Pass();
}
[Test]
public void DeserializeDictionary() {
//var dict = JsonConvert.DeserializeObject<Dictionary<string, object>>("{\"id\": 123, \"nest\": { \"count\": 1 }}",
// new DictionaryConverter());
var json = "{\"id\": 123, \"nest\": { \"count\": 1 }, \"arr\": [1, 2, 3], \"na\": null}";
TestContext.Out.WriteLine(JsonConvert.DeserializeObject(json).GetType());
var obj = JsonConvert.DeserializeObject<object>(json, new LeanCloudJsonConverter());
if (obj is IDictionary<string, object>) {
var dict = obj as Dictionary<string, object>;
TestContext.Out.WriteLine(dict.GetType());
TestContext.Out.WriteLine(dict["id"]);
TestContext.Out.WriteLine(dict["nest"].GetType());
TestContext.Out.WriteLine(dict["arr"].GetType());
}
}
[Test]
public void DeserializeList() {
var json = "[1, \"hello\", [2, 3, 4], { \"count\": 22 }]";
TestContext.Out.WriteLine(JsonConvert.DeserializeObject(json).GetType());
var obj = JsonConvert.DeserializeObject<object>(json, new LeanCloudJsonConverter());
if (obj is IList<object>) {
var arr = obj as List<object>;
TestContext.Out.WriteLine(arr.GetType());
TestContext.Out.WriteLine(arr[0]);
TestContext.Out.WriteLine(arr[1].GetType());
TestContext.Out.WriteLine(arr[2].GetType());
TestContext.Out.WriteLine(arr[3].GetType());
}
}
}
}

View File

@ -21,7 +21,7 @@ namespace LeanCloudTests {
var obj = AVObject.Create("Foo");
obj["content"] = "hello, world";
await obj.SaveAsync();
TestContext.Out.WriteLine($"saved at {Thread.CurrentThread.ManagedThreadId}");
TestContext.Out.WriteLine($"{obj.ObjectId} saved at {Thread.CurrentThread.ManagedThreadId}");
Assert.NotNull(obj.ObjectId);
Assert.NotNull(obj.CreatedAt);
Assert.NotNull(obj.UpdatedAt);

View File

@ -10,6 +10,7 @@
<PackageReference Include="nunit" Version="3.11.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.11.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
</ItemGroup>
<ItemGroup>

View File

@ -26,7 +26,7 @@ namespace LeanCloud.Storage.Internal
Method = HttpMethod.Post,
Content = parameters
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t =>
{
var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary<string, object>;
if (!decoded.ContainsKey("result"))
@ -44,7 +44,7 @@ namespace LeanCloud.Storage.Internal
Method = HttpMethod.Post,
Content = parameters
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t =>
{
var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary<string, object>;
if (!decoded.ContainsKey("result"))

View File

@ -7,6 +7,7 @@ using System.Threading;
using System.Threading.Tasks;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace LeanCloud.Storage.Internal
{
@ -38,15 +39,15 @@ namespace LeanCloud.Storage.Internal
/// <param name="downloadProgress"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<Tuple<HttpStatusCode, IDictionary<string, object>>> RunCommandAsync(AVCommand command,
public async Task<Tuple<HttpStatusCode, T>> RunCommandAsync<T>(AVCommand command,
IProgress<AVUploadProgressEventArgs> uploadProgress = null,
IProgress<AVDownloadProgressEventArgs> downloadProgress = null,
CancellationToken cancellationToken = default(CancellationToken)) {
CancellationToken cancellationToken = default) {
var request = new HttpRequestMessage {
RequestUri = command.Uri,
Method = command.Method,
Content = new StringContent(Json.Encode(command.Content))
Content = new StringContent(JsonConvert.SerializeObject(command.Content))
};
var headers = await GetHeadersAsync();
@ -75,31 +76,29 @@ namespace LeanCloud.Storage.Internal
throw new AVException(AVException.ErrorCode.InternalServerError, contentString);
}
if (responseCode < HttpStatusCode.OK || responseCode > HttpStatusCode.PartialContent) {
// 错误处理
var data = JsonConvert.DeserializeObject<Dictionary<string, object>>(contentString, new LeanCloudJsonConverter());
if (data.TryGetValue("code", out object codeObj)) {
AVException.ErrorCode code = (AVException.ErrorCode)codeObj;
string detail = data["error"] as string;
throw new AVException(code, detail);
} else {
throw new AVException(AVException.ErrorCode.OtherCause, contentString);
}
}
if (contentString != null) {
IDictionary<string, object> contentJson = null;
try {
if (contentString.StartsWith("[", StringComparison.Ordinal)) {
var arrayJson = Json.Parse(contentString);
contentJson = new Dictionary<string, object> { { "results", arrayJson } };
} else {
contentJson = Json.Parse(contentString) as IDictionary<string, object>;
}
var data = JsonConvert.DeserializeObject<object>(contentString, new LeanCloudJsonConverter());
return new Tuple<HttpStatusCode, T>(responseCode, (T)data);
} catch (Exception e) {
throw new AVException(AVException.ErrorCode.OtherCause,
"Invalid response from server", e);
}
if (responseCode < HttpStatusCode.OK || responseCode > HttpStatusCode.PartialContent) {
AVClient.PrintLog("error response code:" + responseCode);
int code = (int)(contentJson.ContainsKey("code") ? (int)contentJson["code"] : (int)AVException.ErrorCode.OtherCause);
string error = contentJson.ContainsKey("error") ?
contentJson["error"] as string : contentString;
AVException.ErrorCode ec = (AVException.ErrorCode)code;
throw new AVException(ec, error);
}
return new Tuple<HttpStatusCode, IDictionary<string, object>>(responseCode, contentJson);
}
return new Tuple<HttpStatusCode, IDictionary<string, object>>(responseCode, null);
return new Tuple<HttpStatusCode, T>(responseCode, default);
}
private const string revocableSessionTokenTrueValue = "1";

View File

@ -16,7 +16,7 @@ namespace LeanCloud.Storage.Internal
/// <param name="downloadProgress">Download progress callback.</param>
/// <param name="cancellationToken">The cancellation token for the request.</param>
/// <returns></returns>
Task<Tuple<HttpStatusCode, IDictionary<string, object>>> RunCommandAsync(AVCommand command,
Task<Tuple<HttpStatusCode, T>> RunCommandAsync<T>(AVCommand command,
IProgress<AVUploadProgressEventArgs> uploadProgress = null,
IProgress<AVDownloadProgressEventArgs> downloadProgress = null,
CancellationToken cancellationToken = default(CancellationToken));

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
using System.Net.Http;
@ -27,7 +28,7 @@ namespace LeanCloud.Storage.Internal {
Method = HttpMethod.Post,
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(task => {
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(task => {
cancellationToken.ThrowIfCancellationRequested();
return new AVConfig(task.Result.Item2);
}).OnSuccess(task => {

View File

@ -45,11 +45,11 @@ namespace LeanCloud.Storage.Internal
});
DateTime? createdAt = extractFromDictionary<DateTime?>(mutableData, "createdAt", (obj) =>
{
return AVDecoder.ParseDate(obj as string);
return (DateTime)obj;
});
DateTime? updatedAt = extractFromDictionary<DateTime?>(mutableData, "updatedAt", (obj) =>
{
return AVDecoder.ParseDate(obj as string);
return (DateTime)obj;
});
if (mutableData.ContainsKey("ACL"))

View File

@ -7,6 +7,7 @@ using System.Net;
using System.Net.Http;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
namespace LeanCloud.Storage.Internal
{
@ -57,7 +58,7 @@ namespace LeanCloud.Storage.Internal
}
};
var ret = await AVPlugins.Instance.HttpClient.ExecuteAsync(request, null, null, CancellationToken.None);
var jsonData = Json.Parse(ret.Item2) as Dictionary<string, object>;
var jsonData = JsonConvert.DeserializeObject<Dictionary<string, object>>(ret.Item2, new LeanCloudJsonConverter());
return new FileState {
Name = jsonData["name"] as string,
Url = new Uri(jsonData["url"] as string, UriKind.Absolute),
@ -70,7 +71,7 @@ namespace LeanCloud.Storage.Internal
Path = $"files/{state.ObjectId}",
Method = HttpMethod.Delete
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken);
}
internal Task<Tuple<HttpStatusCode, IDictionary<string, object>>> GetFileToken(FileState fileState, CancellationToken cancellationToken)
{
@ -89,7 +90,7 @@ namespace LeanCloud.Storage.Internal
Method = HttpMethod.Post,
Content = parameters
};
return commandRunner.RunCommandAsync(command);
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command);
}
public Task<FileState> GetAsync(string objectId, string sessionToken, CancellationToken cancellationToken)
{
@ -97,7 +98,7 @@ namespace LeanCloud.Storage.Internal
Path = $"files/{objectId}",
Method = HttpMethod.Get
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(_ =>
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(_ =>
{
var result = _.Result;
var jsonData = result.Item2;

View File

@ -6,8 +6,7 @@ using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
using LeanCloud.Storage.Internal;
using Newtonsoft.Json;
namespace LeanCloud.Storage.Internal
{
@ -182,7 +181,8 @@ namespace LeanCloud.Storage.Internal
Data = tempStream
};
var ret = await AVPlugins.Instance.HttpClient.ExecuteAsync(request, null, null, CancellationToken.None);
var result = new Tuple<HttpStatusCode, IDictionary<string, object>>(ret.Item1, Json.Parse(ret.Item2) as Dictionary<string, object>);
var result = new Tuple<HttpStatusCode, IDictionary<string, object>>(ret.Item1,
JsonConvert.DeserializeObject<Dictionary<string, object>>(ret.Item2, new LeanCloudJsonConverter()));
return result;
}
public static Stream HttpUploadFile(byte[] file, string fileName, out string contentType, out long contentLength, IDictionary<string, object> nvc)

View File

@ -166,7 +166,7 @@ namespace LeanCloud.Storage.Internal
Method = HttpMethod.Post,
Content = parameters
};
return commandRunner.RunCommandAsync(command);
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command);
}
IList<KeyValuePair<string, string>> GetQiniuRequestHeaders(FileState state)
{

View File

@ -21,7 +21,7 @@ namespace LeanCloud.Storage.Internal {
Path = $"classes/{Uri.EscapeDataString(state.ClassName)}/{Uri.EscapeDataString(state.ObjectId)}",
Method = HttpMethod.Get
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t => {
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t => {
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
});
}
@ -34,7 +34,7 @@ namespace LeanCloud.Storage.Internal {
Path = $"classes/{Uri.EscapeDataString(state.ClassName)}/{Uri.EscapeDataString(state.ObjectId)}?{AVClient.BuildQueryString(queryString)}",
Method = HttpMethod.Get
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t => {
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t => {
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
});
}
@ -49,7 +49,7 @@ namespace LeanCloud.Storage.Internal {
Method = state.ObjectId == null ? HttpMethod.Post : HttpMethod.Put,
Content = objectJSON
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t => {
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t => {
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
serverState = serverState.MutatedClone(mutableClone => {
mutableClone.IsNew = t.Result.Item1 == System.Net.HttpStatusCode.Created;
@ -89,7 +89,7 @@ namespace LeanCloud.Storage.Internal {
Path = $"classes/{state.ClassName}/{state.ObjectId}",
Method = HttpMethod.Delete
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken);
}
public IList<Task> DeleteAllAsync(IList<IObjectState> states,
@ -157,7 +157,7 @@ namespace LeanCloud.Storage.Internal {
{ "requests", encodedRequests }
}
};
commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t => {
commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).ContinueWith(t => {
if (t.IsFaulted || t.IsCanceled) {
foreach (var tcs in tcss) {
if (t.IsFaulted) {

View File

@ -50,7 +50,7 @@ namespace LeanCloud.Storage.Internal
AVUser user,
CancellationToken cancellationToken) where T : AVObject
{
string sessionToken = user != null ? user.SessionToken : null;
string sessionToken = user?.SessionToken;
var parameters = query.BuildParameters();
parameters["limit"] = 1;
@ -78,7 +78,7 @@ namespace LeanCloud.Storage.Internal
Path = $"{relativeUri}?{AVClient.BuildQueryString(parameters)}",
Method = HttpMethod.Get
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t =>
{
return t.Result.Item2;
});

View File

@ -17,7 +17,7 @@ namespace LeanCloud.Storage.Internal {
Path = "sessions/me",
Method = HttpMethod.Get
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t => {
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t => {
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
});
}
@ -27,7 +27,7 @@ namespace LeanCloud.Storage.Internal {
Path = "logout",
Method = HttpMethod.Post
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken);
}
public Task<IObjectState> UpgradeToRevocableSessionAsync(string sessionToken, CancellationToken cancellationToken) {
@ -35,7 +35,7 @@ namespace LeanCloud.Storage.Internal {
Path = "upgradeToRevocableSession",
Method = HttpMethod.Post,
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t => {
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t => {
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
});
}

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.IO;
using System.Collections.Generic;
using System.Threading;
using Newtonsoft.Json;
namespace LeanCloud.Storage.Internal
{
@ -29,7 +30,7 @@ namespace LeanCloud.Storage.Internal
{
string json;
locker.EnterReadLock();
json = Json.Encode(dictionary);
json = JsonConvert.SerializeObject(dictionary);
locker.ExitReadLock();
using (var sw = new StreamWriter(filePath)) {
return sw.WriteAsync(json);
@ -42,7 +43,7 @@ namespace LeanCloud.Storage.Internal
var text = await sr.ReadToEndAsync();
Dictionary<string, object> result = null;
try {
result = Json.Parse(text) as Dictionary<string, object>;
result = JsonConvert.DeserializeObject<Dictionary<string, object>>(text, new LeanCloudJsonConverter());
} catch (Exception e) {
AVClient.PrintLog(e.Message);
}

View File

@ -5,6 +5,7 @@ using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using LeanCloud.Storage.Internal;
using Newtonsoft.Json;
namespace LeanCloud.Storage.Internal
{
@ -66,7 +67,7 @@ namespace LeanCloud.Storage.Internal
saveTask = storageController
.LoadAsync()
.OnSuccess(t => t.Result.AddAsync("CurrentUser", Json.Encode(data)))
.OnSuccess(t => t.Result.AddAsync("CurrentUser", JsonConvert.SerializeObject(data)))
.Unwrap();
}
CurrentUser = user;
@ -96,7 +97,7 @@ namespace LeanCloud.Storage.Internal
AVUser user = null;
if (userDataString != null)
{
var userData = Json.Parse(userDataString) as IDictionary<string, object>;
var userData = JsonConvert.DeserializeObject<Dictionary<string, object>>(userDataString, new LeanCloudJsonConverter());
var state = AVObjectCoder.Instance.Decode(userData, AVDecoder.Instance);
user = AVObject.FromState<AVUser>(state, "_User");
}

View File

@ -25,7 +25,7 @@ namespace LeanCloud.Storage.Internal
Method = HttpMethod.Post,
Content = objectJSON
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t =>
{
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
serverState = serverState.MutatedClone(mutableClone =>
@ -54,7 +54,7 @@ namespace LeanCloud.Storage.Internal
Method = HttpMethod.Post,
Content = data
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t =>
{
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
serverState = serverState.MutatedClone(mutableClone =>
@ -80,7 +80,7 @@ namespace LeanCloud.Storage.Internal
{ "authData", authData}
}
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t =>
{
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
serverState = serverState.MutatedClone(mutableClone =>
@ -97,7 +97,7 @@ namespace LeanCloud.Storage.Internal
Path = "users/me",
Method = HttpMethod.Get
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t =>
{
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
});
@ -112,7 +112,7 @@ namespace LeanCloud.Storage.Internal
{ "email", email}
}
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken);
}
public Task<IObjectState> LogInWithParametersAsync(string relativeUrl, IDictionary<string, object> data,
@ -123,7 +123,7 @@ namespace LeanCloud.Storage.Internal
Method = HttpMethod.Post,
Content = data
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t =>
{
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
serverState = serverState.MutatedClone(mutableClone =>
@ -144,7 +144,7 @@ namespace LeanCloud.Storage.Internal
{ "new_password", newPassword },
}
};
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
return commandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken);
}
public Task<IObjectState> RefreshSessionTokenAsync(string userId, string sessionToken,
@ -154,7 +154,7 @@ namespace LeanCloud.Storage.Internal
Path = $"users/{userId}/refreshSessionToken",
Method = HttpMethod.Put
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t =>
{
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
return serverState;

View File

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace LeanCloud.Storage.Internal {
public class LeanCloudJsonConverter : JsonConverter {
public override bool CanConvert(Type objectType) {
return objectType == typeof(object);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
serializer.Serialize(writer, value);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
if (reader.TokenType == JsonToken.StartObject) {
var obj = new Dictionary<string, object>();
serializer.Populate(reader, obj);
return obj;
}
if (reader.TokenType == JsonToken.StartArray) {
var arr = new List<object>();
serializer.Populate(reader, arr);
return arr;
}
return serializer.Deserialize(reader);
}
}
}

View File

@ -9,6 +9,7 @@ using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace LeanCloud
{
@ -348,7 +349,7 @@ namespace LeanCloud
select string.Format("{0}={1}",
Uri.EscapeDataString(pair.Key),
Uri.EscapeDataString(string.IsNullOrEmpty(valueString) ?
Json.Encode(pair.Value) : valueString)))
JsonConvert.SerializeObject(pair.Value) : valueString)))
.ToArray());
}
@ -365,12 +366,12 @@ namespace LeanCloud
internal static IDictionary<string, object> DeserializeJsonString(string jsonData)
{
return Json.Parse(jsonData) as IDictionary<string, object>;
return JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonData, new LeanCloudJsonConverter());
}
internal static string SerializeJsonString(IDictionary<string, object> jsonData)
{
return Json.Encode(jsonData);
return JsonConvert.SerializeObject(jsonData);
}
//public static Task<Tuple<HttpStatusCode, string>> HttpGetAsync(Uri uri)
@ -419,10 +420,11 @@ namespace LeanCloud
IDictionary<string, object> strs = null;
try
{
strs = (!item2.StartsWith("[", StringComparison.Ordinal) ? AVClient.DeserializeJsonString(item2) : new Dictionary<string, object>()
strs = !item2.StartsWith("[", StringComparison.Ordinal) ? AVClient.DeserializeJsonString(item2) : new Dictionary<string, object>()
{
{ "results", Json.Parse(item2) }
});
{ "results", JsonConvert.DeserializeObject<Dictionary<string, object>>(item2, new LeanCloudJsonConverter()) }
};
}
catch (Exception exception)
{
@ -440,13 +442,11 @@ namespace LeanCloud
internal static Task<Tuple<HttpStatusCode, IDictionary<string, object>>> RunCommandAsync(AVCommand command)
{
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command);
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
}
internal static bool IsSuccessStatusCode(HttpStatusCode responseStatus)
{
var codeValue = (int)responseStatus;
return (codeValue > 199) && (codeValue < 204);
internal static bool IsSuccessStatusCode(HttpStatusCode responseStatus) {
return (responseStatus >= HttpStatusCode.OK) && (responseStatus <= HttpStatusCode.PartialContent);
}
}
}

View File

@ -5,6 +5,7 @@ using System.Threading;
using System.Threading.Tasks;
using LeanCloud.Storage.Internal;
using System.Net.Http;
using Newtonsoft.Json;
namespace LeanCloud {
/// <summary>
@ -129,7 +130,7 @@ namespace LeanCloud {
Method = HttpMethod.Post,
Content = strs
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
@ -203,7 +204,7 @@ namespace LeanCloud {
Method = HttpMethod.Post,
Content = strs
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
@ -233,7 +234,7 @@ namespace LeanCloud {
Content = body
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
@ -262,7 +263,7 @@ namespace LeanCloud {
var command = new AVCommand {
Path = $"verifySmsCode/{code.Trim()}?mobilePhoneNumber={mobilePhoneNumber.Trim()}",
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
@ -309,7 +310,7 @@ namespace LeanCloud {
Path = $"requestCaptcha?width={width}&height={height}",
Method = HttpMethod.Get
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t =>
{
var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary<string, object>;
return new Captcha()
@ -338,7 +339,7 @@ namespace LeanCloud {
Method = HttpMethod.Post,
Content = data
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).ContinueWith(t =>
{
if (!t.Result.Item2.ContainsKey("validate_token"))
throw new KeyNotFoundException("validate_token");
@ -357,7 +358,7 @@ namespace LeanCloud {
Path = $"statistics/apps/{AVClient.CurrentConfiguration.ApplicationId}/sendPolicy",
Method = HttpMethod.Get
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(t =>
{
var settings = t.Result.Item2;
var CloudParameters = settings["parameters"] as IDictionary<string, object>;
@ -390,7 +391,7 @@ namespace LeanCloud {
{ "session_token", user.SessionToken }
}
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).ContinueWith(t =>
{
var body = t.Result.Item2;
return new RealtimeSignature()
@ -471,8 +472,9 @@ namespace LeanCloud {
{
_encode = n =>
{
if (n != null)
return Json.Parse(n.ToString()) as IDictionary<string, object>;
if (n != null) {
return JsonConvert.DeserializeObject<Dictionary<string, object>>(n.ToString(), new LeanCloudJsonConverter());
}
return null;
};
}

View File

@ -369,7 +369,7 @@ namespace LeanCloud
};
}
return AVPlugins.Instance.CommandRunner.RunCommandAsync(cmd).ContinueWith(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(cmd).ContinueWith(t =>
{
var result = t.Result.Item2;
this.state.ObjectId = result["objectId"].ToString();

View File

@ -6,6 +6,7 @@ using System.Threading;
using System.Threading.Tasks;
using LeanCloud.Storage.Internal;
using System.Net.Http;
using Newtonsoft.Json;
namespace LeanCloud
{
@ -301,7 +302,7 @@ namespace LeanCloud
public static Task<IEnumerable<T>> DoCloudQueryAsync(string cqlTeamplate, params object[] pvalues)
{
string queryStringTemplate = "cloudQuery?cql={0}&pvalues={1}";
string pSrting = Json.Encode(pvalues);
string pSrting = JsonConvert.SerializeObject(pvalues);
string queryString = string.Format(queryStringTemplate, Uri.EscapeDataString(cqlTeamplate), Uri.EscapeDataString(pSrting));
return rebuildObjectFromCloudQueryResult(queryString);
@ -313,7 +314,7 @@ namespace LeanCloud
Path = queryString,
Method = HttpMethod.Get
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: CancellationToken.None).OnSuccess(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: CancellationToken.None).OnSuccess(t =>
{
var items = t.Result.Item2["results"] as IList<object>;
var className = t.Result.Item2["className"].ToString();

View File

@ -71,7 +71,7 @@ namespace LeanCloud
Path = $"users/me?session_token={CurrentSessionToken}",
Method = HttpMethod.Get
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
@ -301,7 +301,7 @@ namespace LeanCloud
Method = HttpMethod.Post,
Content = data
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
@ -318,7 +318,7 @@ namespace LeanCloud
Path = $"users/{ObjectId}/friendship/{userObjectId}",
Method = HttpMethod.Delete
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
@ -1050,7 +1050,7 @@ namespace LeanCloud
Method = HttpMethod.Post,
Content = strs
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
@ -1189,7 +1189,7 @@ namespace LeanCloud
Method = HttpMethod.Post,
Content = strs
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
@ -1225,7 +1225,7 @@ namespace LeanCloud
Method = HttpMethod.Put,
Content = strs
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
@ -1286,7 +1286,7 @@ namespace LeanCloud
Method = HttpMethod.Post,
Content = strs
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
@ -1316,7 +1316,7 @@ namespace LeanCloud
Path = $"verifyMobilePhone/{code.Trim()}?mobilePhoneNumber={mobilePhoneNumber.Trim()}",
Method = HttpMethod.Post
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
@ -1333,7 +1333,7 @@ namespace LeanCloud
Path = $"verifyMobilePhone/{code.Trim()}",
Method = HttpMethod.Post
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
@ -1371,7 +1371,7 @@ namespace LeanCloud
Method = HttpMethod.Post,
Content = strs
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});

View File

@ -157,7 +157,7 @@ namespace LeanCloud {
Method = HttpMethod.Post,
Content = data
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
try {
var leaderboard = Parse(t.Result.Item2);
return leaderboard;
@ -219,7 +219,7 @@ namespace LeanCloud {
Method = HttpMethod.Post,
Content = data
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
try {
List<AVStatistic> statisticList = new List<AVStatistic>();
List<object> list = t.Result.Item2["results"] as List<object>;
@ -253,7 +253,7 @@ namespace LeanCloud {
Path = path,
Method = HttpMethod.Post
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
try {
List<AVStatistic> statisticList = new List<AVStatistic>();
List<object> list = t.Result.Item2["results"] as List<object>;
@ -286,7 +286,7 @@ namespace LeanCloud {
Path = path,
Method = HttpMethod.Delete,
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command);
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
}
/// <summary>
@ -302,7 +302,7 @@ namespace LeanCloud {
Path = path,
Method = HttpMethod.Get
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
List<AVLeaderboardArchive> archives = new List<AVLeaderboardArchive>();
List<object> list = t.Result.Item2["results"] as List<object>;
foreach (object obj in list) {
@ -362,7 +362,7 @@ namespace LeanCloud {
Path = path,
Method = HttpMethod.Get
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
try {
List<AVRanking> rankingList = new List<AVRanking>();
List<object> list = t.Result.Item2["results"] as List<object>;
@ -413,7 +413,7 @@ namespace LeanCloud {
Method = HttpMethod.Put,
Content = data
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
return t.Result.Item2;
});
}
@ -428,7 +428,7 @@ namespace LeanCloud {
Path = path,
Method = HttpMethod.Get
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
try {
// 反序列化 Leaderboard 对象
var leaderboard = Parse(t.Result.Item2);
@ -449,7 +449,7 @@ namespace LeanCloud {
Path = path,
Method = HttpMethod.Put
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
try {
Init(t.Result.Item2);
return this;
@ -468,7 +468,7 @@ namespace LeanCloud {
Path = path,
Method = HttpMethod.Delete
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command);
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
}
static AVLeaderboard Parse(IDictionary<string, object> data) {