返回

解析Instapaper API响应:非标准JSON数据处理

IOS

处理 Instapaper API 响应

Instapaper API 返回的响应数据结构看似 JSON,实际却不符合标准的 JSON 格式,它使用类似 ( { ... }, { ... }, ... ) 的结构。这使得直接将其解析为 NSDictionary 或其他常见 JSON 对象变得困难。问题的核心在于响应格式是数组结构,但最外层缺少了标准JSON语法的方括号[],并且其中某些键值对在iOS对象格式化时可能使用了不常见的等于号 =。 需要额外的处理步骤才能解析此类数据。

问题分析

该响应数据本质上是一个类似 JSON 的列表,或者可以被视为一个PropertyList。 它使用了小括号() 嵌套花括号 {} 的结构来表示对象列表, 而不是标准JSON采用的中括号[]嵌套花括号。另外,键值对采用 = 而不是 : 也不是标准的JSON。
标准的 JSON 解析器通常无法直接处理此类格式。必须先将响应格式转换成合法的JSON字符串,才能使用JSON解析器进行处理。

解决方案一:手动转换格式为 JSON

一种直接的方法是使用字符串操作手动转换响应格式为合法的JSON。这涉及以下步骤:

  1. 去除外层的圆括号 () : 使用字符串替换方法去除响应数据最外层的 ()
  2. 替换 =: : 将所有的 = 替换为标准的 JSON 分隔符 :
  3. 将格式转换成为JSON标准数组格式: : 添加方括号[],使其成为符合JSON标准的数组形式。
  4. 解析 JSON 字符串 : 使用标准 JSON 解析器,例如 NSJSONSerialization 在 iOS/macOS 或其他对应环境的 JSON 解析库,将转换后的字符串解析为对象或字典数组。

示例代码(Python):

import json
def process_instapaper_response(response_string):
    # 去除外层圆括号
    response_string = response_string.strip()[1:-1].strip()  
    # 将等号替换为冒号
    response_string = response_string.replace(' = ', ' : ')
     # 添加中括号形成数组格式
    response_string = "["+response_string+"]"
    try:
       data = json.loads(response_string)
       return data
    except json.JSONDecodeError as e:
        print(f"Error decoding JSON: {e}")
        return None
   
# 示例数据(复制请求中返回的内容)
response_string = """
    2013-05-30 19:54:20.155 --[53078:c07] (
        {
        type = meta;
    },
        {
        "subscription_is_active" = 1;
        type = user;
        "user_id" = --;
        username = "[email protected]";
    },
        {
        "bookmark_id" = 387838931;
        description = "";
        hash = YHwQuwhW;
        "private_source" = "";
        progress = 0;
        "progress_timestamp" = 0;
        starred = 0;
        time = 1369954406;
        title = "Adobe Finally Releases Kuler Color-Picking App for iPhone - Mac Rumors";
        type = bookmark;
        url = "http://www.macrumors.com/2013/05/30/adobe-finally-releases-kuler-color-picking-app-for-iphone/";
    },
)
"""
parsed_data = process_instapaper_response(response_string)
if parsed_data:
   # 使用字典数组的数据进行操作
    print(json.dumps(parsed_data,indent=2))

操作步骤:

  1. 复制并运行以上代码,在输出结果中即可得到标准json格式的数据。
  2. 根据实际情况调整代码中的 response_string 为您实际的API响应。

解决方案二:尝试PropertyList解析 (对于特定场景)

如果确定该格式更接近Property List 而不是JSON,某些环境中可能提供PropertyList解析器可以直接使用, 尤其是在使用Apple 相关技术的情况下。Property List 的文件格式和某些特殊响应很相似,只是有特定限制条件:如键必须是字符串。 但是这个解决方案并不总是可行,取决于具体语言或框架是否直接支持处理这种嵌套结构。

示例代码(使用python plistlib尝试):

import plistlib
def process_instapaper_response_plist(response_string):
    
     response_string = response_string.strip()[1:-1].strip()
     # 使用字节表示 plist 格式内容。
     plist_string = bytes(response_string,"utf-8")
     try:
         
          data = plistlib.loads(b'('+ plist_string+b')') #需要字节化
          return data
     except Exception as e:
          print(f"Error: {e}")
          return None
# 示例数据(复制请求中返回的内容)
response_string = """
    2013-05-30 19:54:20.155 --[53078:c07] (
        {
        type = meta;
    },
        {
        "subscription_is_active" = 1;
        type = user;
        "user_id" = --;
        username = "[email protected]";
    },
        {
        "bookmark_id" = 387838931;
        description = "";
        hash = YHwQuwhW;
        "private_source" = "";
        progress = 0;
        "progress_timestamp" = 0;
        starred = 0;
        time = 1369954406;
        title = "Adobe Finally Releases Kuler Color-Picking App for iPhone - Mac Rumors";
        type = bookmark;
        url = "http://www.macrumors.com/2013/05/30/adobe-finally-releases-kuler-color-picking-app-for-iphone/";
    },
)
"""

parsed_data = process_instapaper_response_plist(response_string)
if parsed_data:
     # 使用plist 数组数据进行操作
     import json
     print(json.dumps(parsed_data,indent=2))

操作步骤:

  1. 尝试运行上述python 代码,观察输出。 此方式受限于plistlib,只有键和值满足Property List的限制才能解析成功,如果无法解析仍然应该使用第一个方案。
  2. 替换为真实 API 返回的数据进行测试。

安全建议

  1. 数据验证 : 转换后的 JSON 或 Property List 数据在使用前要进行校验,确保数据的完整性和有效性,避免由于不期望的格式导致应用出错。
  2. 错误处理 : 在 JSON 或 Property List 解析过程中添加完善的错误处理,当数据解析失败时可以有更明确的提示或补救措施,提升应用的稳定性。
  3. 敏感数据 : 对于包含敏感信息,如用户id或者订阅状态的API,在存储和传输中都要考虑加密,保护用户信息。
  4. 日志记录 适当的记录API请求的响应内容, 对于解决数据问题会带来帮助,同时建议只在开发环境或者有授权权限的环境下记录敏感数据。