ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Android JSON解析总结

Android JSON解析总结

文章目录

  • Android JSON解析总结
    • 概述
    • 语法
    • 使用Android的org.json处理
      • 生成JSON
      • 解析JSON

Android JSON解析总结

概述

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式

语法

JSON有2种结构:

  • 对象(Object):JSON中的对象表示为花括号{}中的键值对集合。键和值之间用冒号:连接,键值对之间用逗号,连接。
  • 数组(Array):JSON中的数组表示为方括号[]中的值列表。数组元素之间用逗号,连接。

语法上的硬性约束(写手写 JSON 时最容易踩):键必须用双引号包裹,不能用单引号;最后一个元素不能有尾随逗号;标准 JSON不支持注释;值只能是string / number / boolean / null / object / array六种,不支持undefined、不支持NaN、Infinity。

使用Android的org.json处理

数据类:

publicclassStudent{Stringname;intage;Stringsex;publicStudent(Stringname,intage,Stringsex){this.name=name;this.age=age;this.sex=sex;}}publicclassSchool{Stringteacher;intschoolRanking;List<Student>students;publicSchool(Stringteacher,intschoolRanking,List<Student>students){this.teacher=teacher;this.schoolRanking=schoolRanking;this.students=students;}}

生成JSON

privatevoidtoJson()throwsJSONException,IOException{JSONObjectschoolObject=newJSONObject();// 坑1:put(String, Object) 传入 null 时等价于删除该 key,字段会直接消失,// 要显式写 null 必须用 JSONObject.NULLschoolObject.put("teacher",school.teacher!=null?school.teacher:JSONObject.NULL);schoolObject.put("schoolRanking",school.schoolRanking);JSONArraystudentArray=newJSONArray();// 坑2:集合为 null 时直接 foreach 会 NPEif(school.students!=null){for(Studentstudent:school.students){JSONObjectstudentObject=newJSONObject();studentObject.put("name",student.name!=null?student.name:JSONObject.NULL);studentObject.put("age",student.age);studentObject.put("sex",student.sex!=null?student.sex:JSONObject.NULL);studentArray.put(studentObject);}}schoolObject.put("students",studentArray);// 坑3:getBytes() 不带字符集,依赖平台默认编码,必须显式指定 UTF-8// 坑4:原写法未用 try-with-resources / finally,异常时流不会关闭try(OutputStreamoutputStream=newBufferedOutputStream(newFileOutputStream(newFile(getCacheDir(),"test.json")))){outputStream.write(schoolObject.toString().getBytes(StandardCharsets.UTF_8));}}

解析JSON

privateSchoolparseJson()throwsJSONException,IOException{Filefile=newFile(getCacheDir(),"test.json");JSONObjectjsonObject=newJSONObject(readText(file));// 坑5:getString / getInt 在字段缺失或类型不符时直接抛 JSONException,// 字段不确定的场景优先用 optXxx(key, 默认值)Stringteacher=jsonObject.optString("teacher","");intschoolRanking=jsonObject.optInt("schoolRanking",-1);JSONArraystudentsArray=jsonObject.optJSONArray("students");List<Student>students=newArrayList<>();if(studentsArray!=null){for(inti=0;i<studentsArray.length();i++){JSONObjectstudentObject=studentsArray.optJSONObject(i);if(studentObject==null)continue;Stringname=studentObject.optString("name","");intage=studentObject.optInt("age",0);Stringsex=studentObject.optString("sex","");students.add(newStudent(name,age,sex));}}returnnewSchool(teacher,schoolRanking,students);}privatestaticStringreadText(Filefile)throwsIOException{StringBuilderbuilder=newStringBuilder();// 坑6:FileReader 无法指定字符集,必须换成 InputStreamReader + UTF-8try(Readerreader=newBufferedReader(newInputStreamReader(newFileInputStream(file),StandardCharsets.UTF_8))){// 坑7:原示例缓冲区只有 3 个字符,会产生大量无谓的 IO,用 8KBchar[]buffer=newchar[8*1024];intlen;while((len=reader.read(buffer))!=-1){builder.append(buffer,0,len);}}Stringjson=builder.toString();// 坑8:带 UTF-8 BOM 的文件会让 new JSONObject(json) 直接抛 JSONException,先去掉 BOMif(!json.isEmpty()&&json.charAt(0)=='\uFEFF'){json=json.substring(1);}returnjson;}
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进