使用 REST API 和 Android
Consuming REST API with Android
我对此很陌生,所以我遵循了以下教程:Android: Consuming a Remote JSON API with Volley
我能够从我的 API 中获取数据,但是我获取的资源有点复杂,我不知道如何处理它。
这是 JSON 我得到的:
{
"data":[
{
"id":"1",
"image":"http:\/\/lorempixel.com\/600\/600\/technics",
"user":{
"data":{
"id":"667636906616952",
"first_name":"Lowell",
"last_name":"Leuschke",
"email":"Esmeralda.Hessel@hotmail.com",
"joined":{
"date":"2015-10-09 15:03:19",
"timezone_type":3,
"timezone":"UTC"
}
}
},
"location":{
"data":{
"id":"249795421882013",
"name":"Wedding planner EV",
"type":"193705277324704",
"lat":"42.69649",
"lng":"23.32601"
}
},
"tags":{
"data":[
]
},
"likes":{
"data":[
]
}
}
]
}
这是 Post
资源。我获取的方法与教程相同,这里是 parse
方法:
private List<Post> parse(JSONObject json) throws JSONException {
ArrayList<Post> records = new ArrayList<>();
JSONArray jsonPosts = json.getJSONArray("data");
for (int i = 0; i < jsonPosts.length(); i++) {
JSONObject jsonPost = jsonPosts.getJSONObject(i);
String id = jsonPost.getString("id");
String image = jsonPost.getString("image");
Gson gson = new Gson();
final User user = gson.fromJson(jsonPost.getString("user"), User.class);
final Location location = gson.fromJson(jsonPost.getString("location"), Location.class);
Integer likes = jsonPost.getJSONObject("likes").getJSONArray("data").length();
Post record = new Post(id, image, user, location, likes);
records.add(record);
}
return records;
}
以下是类我有
User
:
public class User {
String id;
String firstName;
String lastName;
String email;
ApiDate joined;
public User(String id, String firstName, String lastName, String email, ApiDate joined) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.joined = joined;
}
public String getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getEmail() {
return email;
}
public ApiDate getJoined() {
return joined;
}
public String getPictureUrl() {
return "https://graph.facebook.com/" + this.getId() + "/picture?type=normal";
}
}
Location
:
public class Location {
String id;
String name;
String type;
String lat;
String lng;
public Location(String id, String name, String type, String lat, String lng) {
this.id = id;
this.name = name;
this.type = type;
this.lat = lat;
this.lng = lng;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getType() {
return type;
}
public String getLat() {
return lat;
}
public String getLng() {
return lng;
}
}
和Post
:
import java.util.ArrayList;
public class Post {
String id;
String image;
User user;
Location location;
ArrayList<User> tags;
Integer likes;
public Post(String id, String image, User user, Location location, Integer likes) {
this.id = id;
this.image = image;
this.user = user;
this.location = location;
this.likes = likes;
}
public String getId() {
return id;
}
public String getImage() {
return image;
}
public User getUser() {
return user;
}
public Location getLocation() {
return location;
}
public Integer getLikes() {
return likes;
}
}
问题是在这个 fetch
方法中 User
和 Location
设置不正确。我相信这是错误的,但我不知道如何处理这种情况。在此之后我有一个 PostsAdapter
像这样的东西:
NetworkImageView profilePicture = (NetworkImageView) convertView.findViewById(R.id.profilePicture);
然后:
profilePicture.setImageUrl(post.getUser().getPictureUrl(), userPictureLoader);
但是post.getUser().getPictureUrl()
好像是空的。
根据要求:
JsonObjectRequest request = new JsonObjectRequest(
"http://my.rest.api/api/posts",
null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject jsonObject) {
try {
List<Post> posts = parse(jsonObject);
mAdapter.swapPostRecords(posts);
} catch (JSONException e) {
Toast.makeText(getActivity(), "Unable to parse data: " + e.getMessage(), Toast.LENGTH_SHORT).show();
Log.d("PH_DEBUG:", "Unable to parse data: " + e.getMessage());
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
Toast.makeText(getActivity(), "Unable to fetch data: " + volleyError.getMessage(), Toast.LENGTH_SHORT).show();
Log.d("PH_DEBUG:", "Unable to fetch data: " + volleyError.getMessage());
}
});
VolleyApplication.getInstance().getRequestQueue().add(request);
有几种方法可以解决,但我的建议是:
在你 API 这边,当你编码变量 "image" 时,如果你使用 php,尝试将 url 字符串编码为 "urlencode"编码 JSON.
时避免使用“\ /”
$url_encoded = urlencode($your_url_string);
并使用 "JSON_UNESCAPED_UNICODE" 作为 JSON 编码的选项:
$my = json_encode($my_data,JSON_UNESCAPED_UNICODE);
因此,您可能会在字段 "image":
中看到类似的内容
"https%3A%2F%2Fendeavor.org.br%2profile_image.png"
在 Android 端,当您收到 JSON 字符串时,执行:
try {
myURL_Image_decoded = URLDecoder.decode(my_image_url, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Log.e("URL DECODE", myURL_Image_decoded);
这可能会解决斜杠编码“\ /”的问题。
如评论所述,因为 user
JSONObject 是另一个 data
JSONObject
因此,您应该使用
final User user = gson.fromJson(jsonPost.getJSONObject("user").getString("data"), User.class);
而不是
final User user = gson.fromJson(jsonPost.getString("user"), User.class);
同样的逻辑适用于您的 location
。
P/S:为了避免 NPE,您还应该检查您的 JSON 对象以确保它们不为 null
希望对您有所帮助!
我对此很陌生,所以我遵循了以下教程:Android: Consuming a Remote JSON API with Volley
我能够从我的 API 中获取数据,但是我获取的资源有点复杂,我不知道如何处理它。
这是 JSON 我得到的:
{
"data":[
{
"id":"1",
"image":"http:\/\/lorempixel.com\/600\/600\/technics",
"user":{
"data":{
"id":"667636906616952",
"first_name":"Lowell",
"last_name":"Leuschke",
"email":"Esmeralda.Hessel@hotmail.com",
"joined":{
"date":"2015-10-09 15:03:19",
"timezone_type":3,
"timezone":"UTC"
}
}
},
"location":{
"data":{
"id":"249795421882013",
"name":"Wedding planner EV",
"type":"193705277324704",
"lat":"42.69649",
"lng":"23.32601"
}
},
"tags":{
"data":[
]
},
"likes":{
"data":[
]
}
}
]
}
这是 Post
资源。我获取的方法与教程相同,这里是 parse
方法:
private List<Post> parse(JSONObject json) throws JSONException {
ArrayList<Post> records = new ArrayList<>();
JSONArray jsonPosts = json.getJSONArray("data");
for (int i = 0; i < jsonPosts.length(); i++) {
JSONObject jsonPost = jsonPosts.getJSONObject(i);
String id = jsonPost.getString("id");
String image = jsonPost.getString("image");
Gson gson = new Gson();
final User user = gson.fromJson(jsonPost.getString("user"), User.class);
final Location location = gson.fromJson(jsonPost.getString("location"), Location.class);
Integer likes = jsonPost.getJSONObject("likes").getJSONArray("data").length();
Post record = new Post(id, image, user, location, likes);
records.add(record);
}
return records;
}
以下是类我有
User
:
public class User {
String id;
String firstName;
String lastName;
String email;
ApiDate joined;
public User(String id, String firstName, String lastName, String email, ApiDate joined) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.joined = joined;
}
public String getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getEmail() {
return email;
}
public ApiDate getJoined() {
return joined;
}
public String getPictureUrl() {
return "https://graph.facebook.com/" + this.getId() + "/picture?type=normal";
}
}
Location
:
public class Location {
String id;
String name;
String type;
String lat;
String lng;
public Location(String id, String name, String type, String lat, String lng) {
this.id = id;
this.name = name;
this.type = type;
this.lat = lat;
this.lng = lng;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getType() {
return type;
}
public String getLat() {
return lat;
}
public String getLng() {
return lng;
}
}
和Post
:
import java.util.ArrayList;
public class Post {
String id;
String image;
User user;
Location location;
ArrayList<User> tags;
Integer likes;
public Post(String id, String image, User user, Location location, Integer likes) {
this.id = id;
this.image = image;
this.user = user;
this.location = location;
this.likes = likes;
}
public String getId() {
return id;
}
public String getImage() {
return image;
}
public User getUser() {
return user;
}
public Location getLocation() {
return location;
}
public Integer getLikes() {
return likes;
}
}
问题是在这个 fetch
方法中 User
和 Location
设置不正确。我相信这是错误的,但我不知道如何处理这种情况。在此之后我有一个 PostsAdapter
像这样的东西:
NetworkImageView profilePicture = (NetworkImageView) convertView.findViewById(R.id.profilePicture);
然后:
profilePicture.setImageUrl(post.getUser().getPictureUrl(), userPictureLoader);
但是post.getUser().getPictureUrl()
好像是空的。
根据要求:
JsonObjectRequest request = new JsonObjectRequest(
"http://my.rest.api/api/posts",
null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject jsonObject) {
try {
List<Post> posts = parse(jsonObject);
mAdapter.swapPostRecords(posts);
} catch (JSONException e) {
Toast.makeText(getActivity(), "Unable to parse data: " + e.getMessage(), Toast.LENGTH_SHORT).show();
Log.d("PH_DEBUG:", "Unable to parse data: " + e.getMessage());
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
Toast.makeText(getActivity(), "Unable to fetch data: " + volleyError.getMessage(), Toast.LENGTH_SHORT).show();
Log.d("PH_DEBUG:", "Unable to fetch data: " + volleyError.getMessage());
}
});
VolleyApplication.getInstance().getRequestQueue().add(request);
有几种方法可以解决,但我的建议是:
在你 API 这边,当你编码变量 "image" 时,如果你使用 php,尝试将 url 字符串编码为 "urlencode"编码 JSON.
时避免使用“\ /”$url_encoded = urlencode($your_url_string);
并使用 "JSON_UNESCAPED_UNICODE" 作为 JSON 编码的选项:
$my = json_encode($my_data,JSON_UNESCAPED_UNICODE);
因此,您可能会在字段 "image":
中看到类似的内容"https%3A%2F%2Fendeavor.org.br%2profile_image.png"
在 Android 端,当您收到 JSON 字符串时,执行:
try {
myURL_Image_decoded = URLDecoder.decode(my_image_url, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Log.e("URL DECODE", myURL_Image_decoded);
这可能会解决斜杠编码“\ /”的问题。
如评论所述,因为 user
JSONObject 是另一个 data
JSONObject
因此,您应该使用
final User user = gson.fromJson(jsonPost.getJSONObject("user").getString("data"), User.class);
而不是
final User user = gson.fromJson(jsonPost.getString("user"), User.class);
同样的逻辑适用于您的 location
。
P/S:为了避免 NPE,您还应该检查您的 JSON 对象以确保它们不为 null
希望对您有所帮助!