无法从Google Cloud Firestore转换出JSON对象,求解决方案
解决Firestore读取数据无法转换为JSONObject的问题
你在Firestore数据读取转JSON的过程中踩了个常见的坑——Firestore的toObjects()方法并不是用来直接转换为JSONObject的,它是为自定义POJO类设计的映射工具。下面给你两种可行的解决方案:
方案一:直接从DocumentSnapshot生成JSONObject
如果坚持要用JSONObject来处理数据,你可以先把Firestore的文档数据转成Map<String, Object>,再用这个Map来构造JSONObject。另外注意,你的代码里用了collection(uid).get(),这其实是查询整个以uid命名的集合,而通常我们会把用户数据存在users集合下、以uid为文档ID的单个文档里,先修正这个结构问题:
private void getUserData() { String uid = Objects.requireNonNull(mAuth.getCurrentUser()).getUid(); ffDatabase.collection("users").document(uid).get() .addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() { @Override public void onComplete(@NonNull Task<DocumentSnapshot> task) { if (task.isSuccessful()) { DocumentSnapshot document = task.getResult(); if (document.exists()) { // 将文档数据转为Map,再构造JSONObject Map<String, Object> userMap = document.getData(); try { JSONObject user = new JSONObject(userMap); DataStorageTemporary.getInstance().setJsonUser(user); } catch (JSONException e) { Log.w("ERROR parse JSON", "Failed to convert map to JSONObject", e); } } else { Log.w("ERROR load data", "User document does not exist"); } } else { Log.w("ERROR load data", "Error getting document.", task.getException()); } } }); }
方案二:使用POJO类(推荐)
Firestore官方更推荐用自定义POJO类来映射数据,这样类型更安全,也避免了JSON解析的麻烦。如果之后需要JSON格式,再把POJO转成JSONObject即可:
- 先创建User类:
public class User { private String userId; private String gender; // 必须要有无参构造器,Firestore反射需要 public User() {} // 带参构造器、getter和setter public User(String userId, String gender) { this.userId = userId; this.gender = gender; } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } }
- 读取并转换:
private void getUserData() { String uid = Objects.requireNonNull(mAuth.getCurrentUser()).getUid(); ffDatabase.collection("users").document(uid).get() .addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() { @Override public void onComplete(@NonNull Task<DocumentSnapshot> task) { if (task.isSuccessful()) { DocumentSnapshot document = task.getResult(); if (document.exists()) { // 直接映射到User对象 User user = document.toObject(User.class); // 如果需要转成JSONObject try { JSONObject userJson = new JSONObject(new Gson().toJson(user)); DataStorageTemporary.getInstance().setJsonUser(userJson); } catch (JSONException e) { Log.w("ERROR parse JSON", "Failed to convert User to JSONObject", e); } } else { Log.w("ERROR load data", "User document does not exist"); } } else { Log.w("ERROR load data", "Error getting document.", task.getException()); } } }); }
为什么你的原代码不行?
task.getResult().toObjects(JSONObject.class)失败的核心原因是:Firestore的toObjects()需要目标类有无参构造器,并且能通过反射将字段一一映射进去,但JSONObject并不符合这个要求——它没有标准的字段映射逻辑,Firestore无法自动把文档数据填充到JSONObject实例里。
内容的提问来源于stack exchange,提问作者Canato
相关产品推荐
相关产品推荐

