### 1、Json 数据类型和概念定义



| 类型 | 描述 | 分类 | 备注与示例 |
| -------- | -------- | -------- | -------- |
| Undefined     | 未定义     |  空类型     |  表示不存在，例：`new ONode()`  |
| Null               | null     |   /    |  表示存在但为null，例：`new ONode(null)`  |
| | | |    |
| Boolean     | 布尔      | 值类型     | 例：`new ONode(true)`   |
| Number     | 数字      | 值类型     |  例：`new ONode(11)`  |
| String       | 字符串    | 值类型     |  例：`new ONode("hello")`  |
| Date         | 时间       | 值类型       |  例：`new ONode(new Date())`   |
| | | |    |
| Array        | 数组     | 数组类型     | 例：`new ONode().asArray()`   |
| Object      | 对象     | 对象类型     |  例：`new ONode().asObject()`   |

* Object 的子项，为 KeyValue 形态，可称为：“成员”
  * 成员分为：键 和 值
* Array 的子项，可成为：“元素”
  * 元素也为：值

### 2、Json Dom 构建主要方法说明

* 对象类型的 `get`，`getOrNew`，`getOrNull`，`set`，`setAll`：

| 方法  | 描述 | 备注|
| -------- | -------- | -------- |
| `get(key)`              | 获取，如果不存在则构建个空节点                             |  在上面做什么都白做，但不会异常    |
| `getOrNew(key)`     | 获取，如果不存在则构建个新节点（并加到父节点）     |       |
| `getOrNull(key)`      | 获取，如果不存在则返回 null                                   |       |
| | | |
| `set(key, val)` | 添加成员 | 符合 Json 数据类型规范 |
| `setAll(map)` | 添加一批成员 | |

使用对象类型的方法时，会自动尝试将 null 转为 object 类型。如果不是 null 且不是 object 类型，则会出现转换异常。null 除了自动转换外，还可使用 `.asObject()` 手动初始化类型。


* 数组类型的 `get`，`getOrNew`，`getOrNull`，`add`，`addAll`：


| 方法  | 描述 | 备注|
| -------- | -------- | -------- |
| `get(index)`              | 获取，如果不存在则构建个空节点                             |      |
| `getOrNew(index)`     | 获取，如果不存在则构建个新节点（并加到父节点）     |       |
| `getOrNull(index)`      | 获取，如果不存在则返回 null                                   |       |
| | | |
| `add(item)`                | 添加元素 | 符合 Json 数据类型规范 |
| `addAll(collection)`     | 添加一批元素 | |

index 支持负数，表过倒着取（例：`get(-1)` 表示倒数第1个）。关于 null 类型自动转换规则与对象类型相同。 


* 节点辅助操作 `fill`，`fillJson`，`then` 方法



| 方法                  | 描述                                                         | 备注          |
| ------------- | ---------------------------------- | -------- |
| `fill(obj)`             | 用一个对象填充自己（完全替换掉）                |  无视类型，会自动编码     |
| `fillJson(json)`     | 用一个 json string 填充自己（完全替换掉）      |       |
| | | |
| `then(slf->{})`      | 然后（进一步链式操作自己）     |      |


* 节点获取方法归类



| 方法                  | 描述                          | 对应检测方法                               | 备注          |
| ------------- | ---------------------------------- | -------- |
| `getArray()`      | 尝试获取数组（List）   | `isArray()`   | 最好先检测，否则可能会异常     |
| `getObject()`     | 尝试获取对象（Map）  | `isObject()`     | 最好先检测，否则可能会异常     |
| | | | |
| `getValue()`      | 尝试获取值（Object）    | `isValue()`   |       |
| `getValueAs()`   | 尝试获取值（T）           |    |  如果类型不对，泛型强转会异常     |
| | | | |
| `getString()`      | 尝试获取值  String      | `isString()`   | 会尝试自动转换     |
| `getBoolean()`   | 尝试获取值  Boolean   | `isBoolean()`   | 会尝试自动转换     |
| `getDate()`        | 尝试获取值  Date        | `isDate()`   | 会尝试自动转换     |
| | | | |
| `getNumber()`    | 尝试获取值  Number   | `isNumber()`   | 最好先检测，否则可能会异常    |
| `getShort()`       | 尝试获取值  Short    |      | 会尝试自动转换     |
| `getInt()`           | 尝试获取值  Integer  |      | 会尝试自动转换     |
| `getLong()`       | 尝试获取值  Long     |    | 会尝试自动转换     |
| `getFloat()`       | 尝试获取值  Float    |     | 会尝试自动转换     |
| `getDouble()`    | 尝试获取值  Double   |     | 会尝试自动转换     |
| | | | |
| | | `isUndefined()` | 是否未定义 |
| | | `isNull()` | 是否为 null |
| | | `isEmpty()` | 是否为空（空数组，或空对象，或空字符串） |



### 3、Json Dom 应用参考

参考1

```java
ONode oNode = new ONode();
oNode.set("id", 1);
oNode.getOrNew("layout").then(o -> {
    o.addNew().set("title", "开始").set("type", "start");
    o.addNew().set("title", "结束").set("type", "end");
});

oNode.get("id").getInt();
oNode.get("layout").get(0).get("title").getString();

oNode.getOrNew("list").fillJson("[1,2,3,4,5,6]");
```

参考2

```java
//构建推送消息
ONode data = new ONode().asObject();
data.set("platform","val");
data.getOrNew("audience").getOrNew("alias").addAll(alias_ary);
data.getOrNew("options").set("apns_production", false);
String message = data.toJson();


//或者....用链式表达式单行构建
public static void push(Collection<String> alias_ary, String text)  {
    ONode data = new ONode().then((d)->{
        d.set("platform", "all");

        d.getOrNew("audience").getOrNew("alias").addAll(alias_ary);

        d.getOrNew("options")
                .set("apns_production",false);

        d.getOrNew("notification").then(n->{
            n.getOrNew("ios")
                    .set("alert",text)
                    .set("badge",0)
                    .set("sound","happy");
        });
    });

    String message = data.toJson();
    String author = Base64Util.encode(appKey+":"+masterSecret);

    Map<String,String> headers = new HashMap<>();
    headers.put("Content-Type","application/json");
    headers.put("Authorization","Basic "+author);

    HttpUtil.postString(apiUrl, message, headers);
}
```
