十、移动平台上的 JSON
如今,移动应用风靡全球——平板电脑和智能移动等设备的销量在世界许多地方超过了个人电脑。 在 iOS 和 Android 等平台的支持下,这些设备包括用于创建和解析 JSON 的 api,作为平台的一部分,这让作为应用开发人员的生活更容易一些。 在本章中有以下几种方法:
- Android 解析 JSON
- 在 Android 上生成 JSON
- 在 Objective-C 中解析 JSON
- 用 Objective-C 在 iOS 上生成 JSON
- 在 iOS 上使用 Swift 解析 JSON
- 在 iOS 上使用 Swift 生成 JSON
- 使用 Qt 解析 JSON
- 使用 Qt 生成 JSON
简介
正如我们在前几章中所讨论的,JSON 是与 web 服务和客户端(无论客户端是 web 应用还是传统应用)通信的绝佳媒介。 对于移动应用来说尤其如此,许多移动应用运行在低带宽的广域网上,与 XML 相比,JSON 的简便性使得总体数据有效负载更小,从而确保远程查询的响应时间更快。
如今领先的移动平台是 Android 和 iOS。 Android 运行 Linux 的变体,支持 Java 软件开发,并在org.json
命名空间中包含一个 JSON 处理器。 iOS,大致来源于 Mach 和 BSD,支持使用 Objective-C, Swift, C 和 c++进行软件开发,尽管对于大多数应用开发,你使用 Objective-C 或 Swift,每个都包含一个绑定到NSJSONSerialization
类,实现 JSON 解析和 JSON 序列化。
移动开发人员的另一个选择是使用跨平台工具包(如 Qt)进行应用开发。 Qt 运行在多种平台上,包括 Android、iOS 和黑莓。 Qt 定义了QJsonDocument
和QJsonObject
类,您可以使用它们在映射和 JSON 之间进行转换。 Qt 是一个已经存在多年的开源框架,它不仅可以在移动平台上运行,还可以在 Mac OS X、Windows 和 Linux 以及许多其他平台上运行。
我们将在接下来的章节中讨论的 JSON 与我们在过去的章节中使用的类似,是一个像这样的文档:
{
'call': 'kf6gpe-7',
'lat': 37.40150,
'lng': -122.03683
'result': 'ok'
}
在接下来的讨论中,我假定您已经正确地为目标平台设置了软件开发环境。 描述为 Android、iOS 和 Qt 设置软件环境的过程会占用比本书更多的篇幅。 如果你有兴趣为特定的移动平台开发软件,你可能需要咨询 Android 或 iOS 的开发者资源:
- 你可以在https://developer.apple.com上找到苹果 iOS 开发者网站。
- 你可以在http://developer.android.com/index.html上找到谷歌 Android 开发者网站。
- 您可以在http://www.qt.io找到有关 Qt 的信息。
Android JSON 解析
AndroidJSONObject
提供了类,它可以让你代表 JSON 文档通过一个接口的名称-值对的概念上类似于一张地图,并通过 getter 和 setter 方法包括序列化和反序列化,访问 JSON 对象的命名字段。
How to do it…
首先用要解析的 JSON 初始化JSONObject
,然后使用它的各种get
方法来获取 JSON 字段的值:
Import org.json.JSONObject;
String json = "…";
JSONObject data = new JSONObject(data);
String call = data.getString("call");
double lat = data.getDouble("lat");
double lng = data.getDouble("lng");
How it works…
JSONObject
构造函数接受 JSON 来解析,并提供访问方法来访问 JSON 的字段。 这里,我们使用getString
和getDouble
访问器分别访问 JSON 的call
、lat
和lng
字段。
JSONObject
类定义了以下访问器:
get
方法,它返回一个子类java.lang.Object
,其中包含指定槽中的值。getBoolean
方法,如果槽中包含Boolean
,返回Boolean
。getDouble
方法,如果槽中包含double
,返回double
。getInt
方法,如果槽中包含int
,返回int
。getJSONArray
方法,其中返回JSONArray
的实例,如果槽包含数组,则返回处理数组的 JSON 解析类JSONArray
。getJSONObject
方法,如果槽包含另一个 map,返回一个JSONObject
实例。getLong
方法,如果槽中包含long
,返回long
。getString
方法,如果槽中包含String
,则返回和String
。
该类还定义了has
和isNull
。 它们接受槽名,如果字段名中有值,返回true
,如果没有字段名或值为null
,则返回true
。
JSONArray
类似于JSONObject
,除了它使用数组而不是映射。 它具有相同的 getter 方法,这些方法接受集合中的整数索引,返回对象、布尔值、字符串、数字等等。
There's more…
JSONObject
类还定义了keys
方法,该方法返回 JSON 中键的Iterator<String>
。 您还可以通过调用names
获取 JSON 中名称中的JSONArray
,或者通过调用length
获取 JSON 中键值对的个数。
参见
更多关于JSONObject
的信息,请参见 Android 文档http://developer.android.com/reference/org/json/JSONObject.html。 更多关于JSONArray
的信息,请参见http://developer.android.com/reference/org/json/JSONArray.html。
在 Android 上生成 JSON
JSONObject
也支持 setter 方法来初始化 JSON 映射中的数据。 使用这些方法,您可以将数据分配给 JSON 对象,然后通过调用其toString
方法获得 JSON 表示。
How to do it…
下面是一个简单的例子:
import org.JSON.JSONObject;
JSONObject data = new JSONObject();
data.put("call", "kf6gpe-7");
data.put("lat", 37.40150);
data.put("lng", -122.03683);
String json = data.toString();
How it works…
多态 put 方法可以接受整数、长整数、对象、布尔值或双精度值,并将指定的值分配给指定的槽。
JSONObject
类定义了toString
方法,该方法采用可选的空格数量来缩进嵌套结构,用于打印精美的 JSON。 如果不传递这个缩进,或者传递 0,实现将以尽可能紧凑的方式编码 JSON。
There's more…
还有putOpt
方法,它接受Object
的任何子类,如果 name 和 value 都是非 null,则将值赋给 name。
您可以通过传递JSONArray
为槽分配值数组,或通过传递另一个JSONObject
作为要设置的值来嵌套映射。 JSONArray
定义了一个类似的 put 方法,它将数组中的整数索引作为第一个参数,而不是槽名。 例如,使用前一个示例中的数据对象,我可以使用以下代码添加一个台站(可能来自无线电电池)的测量电压数组:
import org.JSON.JSONObject;
JSONArray voltages = new JSONArray();
voltages.put(3.1);
voltages.put(3.2);
voltages.put(2.8);
voltages.put(2.6);
data.put("voltages", voltages);
您也可以直接放置java.util.Collection
和java.util.Map
实例,而不是传递JSONArray
或JSONObject
实例。 前面的代码也可以写成:
import org.JSON.JSONObject;
import org.JSON.JSONArray;
import java.util.Collection;
Collection<double> voltages = new Collection<double>();
voltages.put(3.1);
voltages.put(3.2);
voltages.put(2.8);
voltages.put(2.6);
data.put("voltages", voltages);
在构造更复杂的 JSON 对象时,这让事情变得简单一些,因为您不需要将每个 Java 集合或映射包装到相应的 JSON 对象中。
参见
更多关于JSONObject
的信息,请参见 Android 文档http://developer.android.com/reference/org/json/JSONObject.html。 更多关于JSONArray
的信息,请参见http://developer.android.com/reference/org/json/JSONArray.html。
在 iOS 上解析 JSON
Objective-C 的类库定义了NSJSONSerialization
类,它可以序列化为或者从 JSON。 它将 JSON 转换为值的NSDictionary
对象,带有键、JSON 中的槽名和它们的 JSON 值。 它在 iOS 5.0 及更高版本中可用。
How to do it…
下面是一个简单的例子:
NSError* error;
NSDictionary* data = [ NSJSONSerialization
JSONObjectWithData: json
options: kNilOptions
error: &error ];
NSString* call = [ data ObjectForKey: @"call" ];
How it works…
NSJSONSerialization
类有一个方法JSONObjectWithData:options:error
,它接受一个NSString
、解析选项和一个记录错误的地方,并执行 JSON 解析。 它可以接受顶级是数组或字典的 JSON,分别返回NSArray
或NSDictionary
结果。 所有值必须分别为NSString
、NSNumber
、NSArray
、NSDictionary
、NSNull
的实例。 如果顶级对象是一个数组,该方法返回NSArray
; 否则,返回NSDictionary
。
There's more…
默认情况下,此方法返回的数据是不可变的。 如果你想要可变的数据结构,相反,你可以传递选项NSJSONReadingMutableContainers
。 要解析不是数组或字典的顶级字段,请传递选项NSJSONReadingAllowFragments
。
参见
在 iOS 上生成 JSON
您可以也可以使用NSJSONSerializer
类序列化NSDictionary
或NSArray
; 只需使用dataWithJSONObject
方法。
How to do it…
下面是一个简单的例子,假设数据是NSDictionary
,你想要转换成 JSON:
NSError *error;
NSData* jsonData = [NSJSONSerialization
dataWithJSONObject: data
options: NSJSONWritingPrettyPrinted
error: &error];
How it works…
dataWithJSONObject:options:error
方法可以使用NSArray
或NSDictionary
,并返回一个带有所传递集合的编码 JSON 的NSData
blob。 如果您通过kNilOptions
,JSON 将以紧凑的方式编码; 对于漂亮打印的 JSON,可以传递选项NSJSONWritingPrettyPrinted
。
参见
苹果的文档为NSJSONSerialization
类在https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSJSONSerialization_Class/index.html。
在 iOS 上使用 Swift 解析 JSON
同样的NSJSONSerialization
类在苹果用于 iOS 开发的新语言 Swift 中可用。
How to do it…
下面是一个如何在 Swift 中调用NSJSONSerialization
的JSONObjectWithData
方法的示例:
import Foundation
var error: NSError?
Let json: NSData = /* the JSON to parse */
let data = NSJSONSerialization.JSONObjectWithData(json,
options: nil,
error: &error);
How it works…
Swift 中的方法调用看起来像函数调用,参数以(可选的命名)逗号分隔的参数传递,类似于 c++或 Java 中的调用方式。 JSONObjectWithData
的参数与 Objective-C 版本中的方法参数相同。
在 iOS 上使用 Swift 生成 JSON
当然,您也可以从 Swift 调用NSJSONSerialization.dataWithJSONObject
方法,该方法返回一个NSData
对象,然后您可以将其转换为字符串。
How to do it…
下面是一个简单的例子:
var error: NSError?
var data: NSJSONSerialization.dataWithJSONObject(
dictionary,
options: NSJSONWritingOptions(0),
error: &error);
var json: NSString(data: data, encoding: NSUTF8StringEncoding);
How it works…
方法dataWithJSONObject
操作,就像 Objective-C 方法一样。 一旦我们接收到包含 json 编码的字典版本的NSData
,我们使用NSString
构造函数将其转换为NSString
。
使用 Qt 解析 JSON
JSON 解析的 Qt 实现实际上与 Android 版本的界面非常相似。 Qt 定义了QJsonObject
和QJsonArray
类,它们可以分别包含 JSON 映射和 JSON 数组。 解析本身是由QJsonDocument
类完成的,该类有一个静态的fromJson
方法,接受 JSON 并执行必要的解析。
How to do it…
下面是一个简单的例子:
QString json = "{ 'call': 'kf6gpe-7', 'lat': 37.40150, 'lng': -122.03683, 'result': 'ok'}";
QJsonDocument document = QJsonDocument.fromJson(json);
QJsonObject data = document.object;
QString call = data["call"].toString();
How it works…
解析分为两步:首先,代码使用QJsonDocument
解析 JSON,然后使用生成的QJsonObject
访问数据。
QJsonObject
类作为QJsonValue
对象的映射,每个对象都可以使用以下方法转换为它们的基本类型:
toArray
:此方法转换为QJsonArray
toBool
:这个方法转换为布尔值toDouble
:这个方法转换为 doubletoInt
:该方法转换为整数toObject
:该方法转换为另一个QJsonObject
,让您嵌套QJsonObject
的映射toString
:此方法转换为QString
There's more…
您还可以使用 Qt 的foreach
宏或begin
、constBegin
和end
迭代方法来遍历QJsonObject
中的键。 还有一个包含方法,它接受一个槽的名称,如果映射包含您正在寻找的槽,则返回 true。
参见
关于 JSON 解析,请参阅 Qt 文档http://doc.qt.io/qt-5/json.html。
使用 Qt 生成 JSON
QJsonDocument
类还有toJson
方法,它将引用的对象转换为 JSON。
How to do it…
下面的是一个从 JSON 转换回 JSON 的例子,在此过程中很好地打印了 JSON:
QString json = "{ 'call': 'kf6gpe-7', 'lat': 37.40150, 'lng': -122.03683, 'result': 'ok'}";
QJsonDocument document = QJsonDocument.fromJson(json);
QJsonObject data = document.object;
QByteArrayprettyPrintedJson =
document.toJson(QJsonDocumented::Indented);
How it works…
QJsonDocument
类有一个方法toJson
,它将它所引用的文档或数组转换为 JSON。 您可以通过传递QJsonDocument::Indented
请求 JSON 的漂亮打印版本,或者通过传递QJsonDcoument::Compact
请求 JSON 的紧凑版本。
参见
关于QJsonDocument
的更多信息,请参阅http://doc.qt.io/qt-5/qjsondocument.html的 Qt 文档。
版权属于:月萌API www.moonapi.com,转载请注明出处