使用 Json 时出现奇怪的“nameValuePairs”键

使用 Json 时出现奇怪的“nameValuePairs”键

解决nameValuePairs问题

在使用RPC进行传值时,常规的使用了json进行传输。但是当接收端接收后进行解析时格式出现很大问题,多了一层key----nameValueParis。

{
    "command": "report",
    "content": {
        "status": "success",
        "result": {
            "nameValuePairs": {
                "nameValuePairs": {
                    "nameValuePairs": {
                        "text": "",
                        "type": "android.widget.FrameLayout",
                        "value": "",
                        "actions": {
                            "values": [
                                {
                                    "nameValuePairs": {
                                        "mActionId": 4.0
                                    }
                                },
                                {
                                    "nameValuePairs": {
                                        "mActionId": 8.0
                                    }
                                },
                                {
                                    "nameValuePairs": {
                                        "mActionId": 64.0
                                    }
                                },
                                {
                                    "nameValuePairs": {
                                        "mActionId": 1.6908342E7
                                    }
                                }
                            ]
                        },
                        ...

原因

经过排查,发现时JSONObject的问题。JSONObject 通过名称 nameValuePairs 将所有键值映射存储在一个成员变量中。 这是 JSONObject 实现的摘录

public class JSONObject {
    ...
    private final Map<String, Object> nameValuePairs;
    ...
}

解决方案

仔细研究过后,大体分为两种解决方案。第一种是,用JsonObject替换JSONObject;第二种是,利用@Body。

JsonObject

利用JsonObject替换JSONObject虽然可能有点麻烦,但是效果较好。

例如,替换前:

public JSONObject inspectAccessibilitySerializer(TreeNode<AccessibilityNodeInfo> accessibilityNodeInfoTreeNode) throws JSONException {
        JSONObject jsonObject = new JSONObject();
        AccessibilityNodeInfo root = accessibilityNodeInfoTreeNode.getItem();
        jsonObject.put("text", safeCharSeqToString(root.getText()));
        jsonObject.put("type", safeCharSeqToString(root.getClassName()));
        jsonObject.put("value", safeCharSeqToString(root.getContentDescription()));

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
            jsonObject.put("actions", root.getActionList());
        }else {
            jsonObject.put("actions", null);
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            jsonObject.put("hint", root.getHintText());
        }else {
            jsonObject.put("hint", null);
        }

        Rect rect = new Rect();
        root.getBoundsInScreen(rect);
        Position position = new Position();
        position.x = Math.round(rect.centerX() - rect.width()/2);
        position.y = Math.round(rect.centerY() - rect.height()/2);
        position.width = rect.width();
        position.height = rect.height();

        jsonObject.put("position",position);
        jsonObject.put("states",statesFormat(root));

        if (accessibilityNodeInfoTreeNode.getChildren().size() > 0){
            JSONArray children = new JSONArray();
            for(TreeNode<AccessibilityNodeInfo> childNode : accessibilityNodeInfoTreeNode.getChildren()){
                children.put(inspectAccessibilitySerializer(childNode));
            }

            jsonObject.put("children", children);
        }

        return jsonObject;

    }

替换后

private JsonObject inspectAccessibilitySerializer(TreeNode<AccessibilityNodeInfo> accessibilityNodeInfoTreeNode) {
        JsonObject jsonObject = new JsonObject();
        AccessibilityNodeInfo nodeInfo = accessibilityNodeInfoTreeNode.getItem();

        Rect rect = new Rect();
        nodeInfo.getBoundsInScreen(rect);
        JsonObject positionJson = new JsonObject();
        positionJson.addProperty("x", Math.round(rect.centerX() - rect.width() / 2));
        positionJson.addProperty("y", Math.round(rect.centerY() - rect.height() / 2));
        positionJson.addProperty("width", rect.width());
        positionJson.addProperty("height", rect.height());

        jsonObject.add("position", positionJson);
        jsonObject.add("states", statesFormat(nodeInfo));
        jsonObject.addProperty("text", safeCharSeqToString(nodeInfo.getText()));
        jsonObject.addProperty("type", safeCharSeqToString(nodeInfo.getClassName()));
        jsonObject.addProperty("value", safeCharSeqToString(nodeInfo.getContentDescription()));

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            jsonObject.addProperty("hint", safeCharSeqToString(nodeInfo.getHintText()));
        } else {
            jsonObject.addProperty("hint", "");
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            JsonArray actionsArray = new JsonArray();
            for (int i = 0; i < nodeInfo.getActionList().size(); i++) {
                actionsArray.add(nodeInfo.getActionList().get(i).toString());
            }
            jsonObject.add("actions", actionsArray);
        } else {
            jsonObject.addProperty("actions", "");
        }

        if (accessibilityNodeInfoTreeNode.getChildren().size() > 0) {
            JsonArray children = new JsonArray();
            for (TreeNode<AccessibilityNodeInfo> childNode : accessibilityNodeInfoTreeNode.getChildren()) {
                children.add(inspectAccessibilitySerializer(childNode));
            }
            jsonObject.add("children", children);
        }
        return jsonObject;

    }

@Body

将实际的 JAVA 对象传递给 @Body 注释,而不是对应的 JSONObject。 GSON 将负责将其转换为 JSON 表示。这个方法我没有使用,示例来自StackOverflow

class HTTPRequestBody {
   String key1 = "value1";
   String key2 = "value2";
   ...
}

// GSON will serialize it as {"key1": "value1", "key2": "value2"}, 
// which will be become HTTP request body.

public interface MyService {
    @Headers({"Content-type: application/json",
              "Accept: */*"})
    @POST("/test")
    void postJson(@Body HTTPRequestBody body, Callback<Response> callback);
}

// Usage
MyService myService = restAdapter.create(MyService.class);
myService.postJson(new HTTPRequestBody(), callback);

结果

{
    "command": "inspectAccessibility",
    "data": {
        "position": {
            "x": 0,
            "y": 0,
            "width": 1440,
            "height": 2560
        },
        "states": [
            "enable",
            "not clickable"
        ],
        "text": "",
        "type": "android.widget.FrameLayout",
        "value": "",
        "hint": "",
        "actions": [
            "AccessibilityAction: ACTION_SELECT - null",
            "AccessibilityAction: ACTION_CLEAR_SELECTION - null",
            "AccessibilityAction: ACTION_ACCESSIBILITY_FOCUS - null",
            "AccessibilityAction: ACTION_SHOW_ON_SCREEN - null"
        ],
        "children": [
            {
                "position": {
                    "x": 0,
                    "y": 0,
                    "width": 1440,
                    "height": 2392
                },
                "states": [
                    "enable",
                    "not clickable"
                ],
                "text": "",
                "type": "android.view.ViewGroup",
                "value": "",
                "hint": "",
                "actions": [
                    "AccessibilityAction: ACTION_SELECT - null",
                    "AccessibilityAction: ACTION_CLEAR_SELECTION - null",
                    "AccessibilityAction: ACTION_ACCESSIBILITY_FOCUS - null",
                    "AccessibilityAction: ACTION_SHOW_ON_SCREEN - null"
                ],
                ...

总结

JSONObject和JsonObject可用的方法不一样,比如JSONObject.put()因为参数可以是Object所以很多时候会特别方便。

    public JSONObject put(String name, Object value) throws JSONException {
        throw new RuntimeException("Stub!");
    }

而JsonObject.add/addProperty()除常见的String,Boolean等类型外,参数可以是JsonElement

  /**
   * Adds a member, which is a name-value pair, to self. The name must be a String, but the value
   * can be an arbitrary JsonElement, thereby allowing you to build a full tree of JsonElements
   * rooted at this node.
   *
   * @param property name of the member.
   * @param value the member object.
   */
  public void add(String property, JsonElement value) {
    members.put(property, value == null ? JsonNull.INSTANCE : value);
  }

通过源码可以发现JsonElement包含:JsonObject,JsonArray,JsonPrimitive,JsonNull四种类型。

/**
 * A class representing an element of Json. It could either be a {@link JsonObject}, a
 * {@link JsonArray}, a {@link JsonPrimitive} or a {@link JsonNull}.
 *
 * @author Inderjeet Singh
 * @author Joel Leitch
 */
public abstract class JsonElement {
	...
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值