JSON : Placeholder

JSON : Placeholder (https://jsonplaceholder.typicode.com/) 是一个用于测试的 REST API 网站。

以下使用 Task API/Rx.NET + Json.NET 调用该网站的 REST API,获取字符串以及 JSON 数据。

  • GET /posts/1
  • GET /posts
  • POST /posts
  • PUT /posts/1
  • DELETE /posts/1

所有 GET API 都返回JSON数据,格式(JSON-Schema)如下:

{
"type":"object",
"properties": {
"userId": {"type" : "integer"},
"id": {"type" : "integer"},
"title": {"type" : "string"},
"body": {"type" : "string"}
}
}

Post 对象

public class Post
{
[JsonProperty("userId")]
public int UserId { get; set; }
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("body")]
public string Body { get; set; } public override string ToString() =>
$"Post {{userId = {UserId}, id = {Id}, title = \"{Title}\", body = \"{Body.Replace("\n", "\\n")}\"}}";
}

Post 对象负责 .NET 对象和 JSON 数据的相互转换。

Post 类使用了 Json.NET 所提供的 attributes。

Task API

public class PostDataStoreByTask
{
protected HttpClient client = new HttpClient
{
BaseAddress = new Uri("https://jsonplaceholder.typicode.com/")
}; public async Task<string> GetPostAsString(int id) =>
!CrossConnectivity.Current.IsConnected ? null : await client.GetStringAsync($"posts/{id}"); public async Task<Post> GetPostAsJson(int id)
{
if (!CrossConnectivity.Current.IsConnected) return null; var json = await client.GetStringAsync($"posts/{id}");
var item = await Task.Run(() => JsonConvert.DeserializeObject<Post>(json)); return item;
} public async Task<IEnumerable<Post>> GetPosts(int n)
{
IEnumerable<Post> items = new List<Post>();
if (CrossConnectivity.Current.IsConnected)
{
var json = await client.GetStringAsync("posts");
items = await Task.Run(() => JsonConvert.DeserializeObject<IEnumerable<Post>>(json));
}
return items.Take(n);
} private StringContent GetStringContent(Post item) =>
new StringContent(JsonConvert.SerializeObject(item), Encoding.UTF8, "application/json"); public async Task<Post> CreatePost(Post item)
{
if (item == null || !CrossConnectivity.Current.IsConnected) return null; var response = await client.PostAsync("posts", GetStringContent(item));
if (!response.IsSuccessStatusCode) return null; var json = await response.Content.ReadAsStringAsync();
var item2 = await Task.Run(() => JsonConvert.DeserializeObject<Post>(json)); return item2;
} public async Task<Post> UpdatePost(Post item)
{
if (item == null || !CrossConnectivity.Current.IsConnected) return null; var response = await client.PutAsync($"posts/{item.Id}", GetStringContent(item));
if (!response.IsSuccessStatusCode) return null; var json = await response.Content.ReadAsStringAsync();
var item2 = await Task.Run(() => JsonConvert.DeserializeObject<Post>(json)); return item2;
} public async Task<string> DeletePost(int id)
{
if (!CrossConnectivity.Current.IsConnected) return null; var response = await client.DeleteAsync($"posts/{id}");
if (!response.IsSuccessStatusCode) return null; var json = await response.Content.ReadAsStringAsync();
return json;
}
}
  • getPostAsString 方法取出第1个Post,返回字符串
  • getPostAsJson 方法取出第1个Post,返回Post对象
  • getPosts 方法取出前n个Post,返回n个Post对象
  • createPost 方法创建1个Post,返回所创建的Post对象
  • updatePost 方法更新第1个Post,返回所更新的Post对象
  • deletePost 方法删除第1个Post,返回字符串

Rx.NET

public class PostDataStoreByRx
{
protected HttpClient client = new HttpClient
{
BaseAddress = new Uri("https://jsonplaceholder.typicode.com/")
}; public IObservable<string> GetPostAsString(int id) =>
!CrossConnectivity.Current.IsConnected ? Observable.Empty<string>() :
client.GetStringAsync($"posts/{id}").ToObservable(); public IObservable<Post> GetPostAsJson(int id) =>
!CrossConnectivity.Current.IsConnected? Observable.Empty<Post>() :
client.GetStringAsync($"posts/{id}").ToObservable()
.Select(json => JsonConvert.DeserializeObject<Post>(json)); public IObservable<Post> GetPosts(int n) =>
!CrossConnectivity.Current.IsConnected ? Observable.Empty<Post>() :
client.GetStringAsync("posts").ToObservable()
.SelectMany(json => JsonConvert.DeserializeObject<IEnumerable<Post>>(json))
.Take(n); private StringContent GetStringContent(Post item) =>
new StringContent(JsonConvert.SerializeObject(item), Encoding.UTF8, "application/json"); public IObservable<Post> CreatePost(Post item) =>
item == null || !CrossConnectivity.Current.IsConnected ? Observable.Empty<Post>() :
client.PostAsync("posts", GetStringContent(item)).ToObservable()
.SelectMany(response => !response.IsSuccessStatusCode ? Observable.Empty<Post>() :
response.Content.ReadAsStringAsync().ToObservable()
.Select(json => JsonConvert.DeserializeObject<Post>(json))); public IObservable<Post> UpdatePost(Post item) =>
item == null || !CrossConnectivity.Current.IsConnected? Observable.Empty<Post>() :
client.PutAsync($"posts/{item.Id}", GetStringContent(item)).ToObservable()
.SelectMany(response => !response.IsSuccessStatusCode? Observable.Empty<Post>() :
response.Content.ReadAsStringAsync().ToObservable()
.Select(json => JsonConvert.DeserializeObject<Post>(json))); public IObservable<string> DeletePost(int id) =>
!CrossConnectivity.Current.IsConnected ? Observable.Empty<string>() :
client.DeleteAsync($"posts/{id}").ToObservable()
.SelectMany(response => !response.IsSuccessStatusCode ? Observable.Empty<string>() :
response.Content.ReadAsStringAsync().ToObservable());
}

相比较 Task API,Rx.NET 代码简练但是比较难理解。

Main 方法

public static void Main(string[] args)
{
{
var dataStore = new PostDataStoreByTask();
Console.WriteLine(dataStore.GetPostAsString(1).Result);
Console.WriteLine(dataStore.GetPostAsJson(1).Result);
dataStore.GetPosts(2).Result.ToList().ForEach(Console.WriteLine);
Console.WriteLine(dataStore.CreatePost(new Post
{
UserId = 101,
Id = 0,
Title = "test title",
Body = "test body"
}).Result);
Console.WriteLine(dataStore.UpdatePost(new Post
{
UserId = 101,
Id = 1,
Title = "test title",
Body = "test body"
}).Result);
Console.WriteLine(dataStore.DeletePost(1).Result);
}
{
var dataStore = new PostDataStoreByRx();
dataStore.GetPostAsString(1).Subscribe(Console.WriteLine);
dataStore.GetPostAsJson(1).Subscribe(Console.WriteLine);
dataStore.GetPosts(2).Do(Console.WriteLine).Subscribe();
dataStore.CreatePost(new Post
{
UserId = 101,
Id = 0,
Title = "test title",
Body = "test body"
}).Subscribe(Console.WriteLine);
dataStore.UpdatePost(new Post
{
UserId = 101,
Id = 1,
Title = "test title",
Body = "test body"
}).Subscribe(Console.WriteLine);
dataStore.DeletePost(1).Subscribe(Console.WriteLine);
Console.ReadKey();
}
}

输出结果

{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
Post {userId = 1, id = 1, title = "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", body = "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"}
Post {userId = 1, id = 1, title = "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", body = "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"}
Post {userId = 1, id = 2, title = "qui est esse", body = "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"}
Post {userId = 101, id = 101, title = "test title", body = "test body"}
Post {userId = 101, id = 1, title = "test title", body = "test body"}
{}
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
Post {userId = 1, id = 1, title = "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", body = "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"}
Post {userId = 1, id = 1, title = "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", body = "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"}
Post {userId = 1, id = 2, title = "qui est esse", body = "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"}
Post {userId = 101, id = 1, title = "test title", body = "test body"}
Post {userId = 101, id = 101, title = "test title", body = "test body"}
{}

ReactiveX 学习笔记(15)使用 Rx.NET + Json.NET 调用 REST API的更多相关文章

  1. ReactiveX 学习笔记(14)使用 RxJava2 + Retrofit2 调用 REST API

    JSON : Placeholder JSON : Placeholder (https://jsonplaceholder.typicode.com/) 是一个用于测试的 REST API 网站. ...

  2. ReactiveX 学习笔记(17)使用 RxSwift + Alamofire 调用 REST API

    JSON : Placeholder JSON : Placeholder (https://jsonplaceholder.typicode.com/) 是一个用于测试的 REST API 网站. ...

  3. ReactiveX 学习笔记(18)使用 RxJS + Angular 调用 REST API

    JSON : Placeholder JSON : Placeholder (https://jsonplaceholder.typicode.com/) 是一个用于测试的 REST API 网站. ...

  4. ReactiveX 学习笔记(0)学习资源

    ReactiveX 学习笔记 ReactiveX 学习笔记(1) ReactiveX 学习笔记(2)创建数据流 ReactiveX 学习笔记(3)转换数据流 ReactiveX 学习笔记(4)过滤数据 ...

  5. Ext.Net学习笔记15:Ext.Net GridPanel 汇总(Summary)用法

    Ext.Net学习笔记15:Ext.Net GridPanel 汇总(Summary)用法 Summary的用法和Group一样简单,分为两步: 启用Summary功能 在Feature标签内,添加如 ...

  6. SQL反模式学习笔记15 分组

    目标:查询得到每组的max(或者min等其他聚合函数)值,并且得到这个行的其他字段 反模式:引用非分组列 单值规则:跟在Select之后的选择列表中的每一列,对于每个分组来说都必须返回且仅返回一直值. ...

  7. ReactiveX 学习笔记(24)使用 RxCpp + C++ REST SDK 调用 REST API

    JSON : Placeholder JSON : Placeholder (https://jsonplaceholder.typicode.com/) 是一个用于测试的 REST API 网站. ...

  8. 【Spring学习笔记-MVC-4】SpringMVC返回Json数据-方式2

    <Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://www ...

  9. 【Spring学习笔记-MVC-3】SpringMVC返回Json数据-方式1

    <Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://www ...

随机推荐

  1. [UE4]用Blenspace混合空间动画代替AimOffset动画偏移

  2. Delphi TstringList Stringlist的特殊用法

    procedure TForm1.btn1Click(Sender : TObject); var   m      : Integer;   s       : string;   strlst   ...

  3. for循环.html

    <script> for (var i = 1; i < 5 ; i++) { alert(i); } 公式需要记住,并多加练习,加深记忆,注意编写格式 for (var i = 1 ...

  4. Android--普通注册页面实现(无功能)

    reg.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmln ...

  5. Call to undefined function think\finfo_open()

    Fileinfo 扩展 - Linux面板- 宝塔面板 上传文件,出现错误 安装的fileinfo扩展

  6. mongodb $用法,等

    1.$修改器 : $set 简单粗暴 {name:value} dict["name"]=value   $unset 简单粗暴的删除字段 {$unset:{name:1}} de ...

  7. Xcode6在iPhone5+iOS7模拟器上编译,上下有黑边问题

    http://94it.net/a/jingxuanboke/2015/0113/447679.html

  8. uva-10487-枚举

    题意:给你一个集合,每俩个数相加得到一个和s,输入s1,问离s1最近的s是多少 二分,注意如果二分出相等,那一定是最近的数,要不然就比较最后mid和mid-1的数 #include <strin ...

  9. Exchange Server and Update Rollup Build Numbers

    原文链接https://social.technet.microsoft.com/wiki/contents/articles/240.exchange-server-and-update-rollu ...

  10. 【转】AD常用端口

    通常在域环境中我们有部分设备在DMZ区时,就需要知道AD的相关端口.在此提供给各位: 用户登录与验证身份时会用到的连接端口用户登录时会用到以下的服务,因此如果用户的计算机与域控制器之间被防火墙隔开,就 ...