Elixir中如何解析mandrill_events并将JSON数组字符串转为Map?
解决Mandrill Events解析失败及JSON数组转Map的问题
我来帮你搞定这两个问题——Mandrill Events解析失败的排查修复,以及JSON对象数组转Map的实现:
一、修复Mandrill Events解析失败的问题
Mandrill发送的mandrill_events参数本质是JSON数组的URL编码字符串,你遇到的解析失败大概率是URL解码不彻底、JSON格式转义异常,或者误把数组当成单个对象解析导致的。按下面的步骤排查修复:
1. 先做URL解码
这是最容易忽略的第一步!Mandrill会对事件数组做URL编码,直接解析编码后的字符串肯定会失败。举两个常见语言的解码示例:
- Java:
import java.net.URLDecoder; import java.nio.charset.StandardCharsets; // 从请求中获取原始的mandrill_events参数 String encodedEvents = request.getParameter("mandrill_events"); // 解码还原成原始JSON字符串 String decodedEvents = URLDecoder.decode(encodedEvents, StandardCharsets.UTF_8);
- Python:
import urllib.parse # 从表单或请求参数中获取值 encoded_events = request.form.get("mandrill_events") # URL解码 decoded_events = urllib.parse.unquote(encoded_events)
2. 校验JSON格式合法性
解码后,把字符串复制到本地的JSON校验工具(比如JSONlint桌面版)里检查,看是否存在语法错误:
- 有没有多余的尾逗号
- 引号是否配对(比如单引号混双引号)
- 数组括号
[]是否闭合
3. 处理双重转义问题
有时候请求中的JSON会被双重转义(比如\"变成\\\"),这时候需要先还原转义字符:
- Java可以用
org.apache.commons.text.StringEscapeUtils.unescapeJava(decodedEvents)处理 - Python可以用
ast.literal_eval(decoded_events)先做转义还原,再用json.loads()解析
4. 正确解析为数组
Mandrill的事件是数组格式,别尝试解析成单个对象!最终解析示例:
- Java(用Jackson):
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.core.type.TypeReference; import java.util.List; import java.util.Map; ObjectMapper objectMapper = new ObjectMapper(); // 解析为Map组成的List List<Map<String, Object>> eventsList = objectMapper.readValue(decodedEvents, new TypeReference<List<Map<String, Object>>>() {}); // 访问指定值,比如获取第一个事件的类型 String firstEventType = (String) eventsList.get(0).get("event");
- Python:
import json events_list = json.loads(decoded_events) # 遍历事件并访问值 for event in events_list: print(f"事件类型:{event.get('event')}")
二、实现JSON对象数组转Map的功能
JSON数组转Map需要先确定Map的key规则,常用两种方案:
方案1:用数组索引作为Map的key
适合不需要业务唯一标识的场景:
- Java:
import com.fasterxml.jackson.databind.ObjectMapper; import java.util.HashMap; import java.util.List; import java.util.Map; import com.fasterxml.jackson.core.type.TypeReference; public Map<Integer, Map<String, Object>> arrayToMapByIndex(String jsonArrayStr) throws Exception { ObjectMapper mapper = new ObjectMapper(); List<Map<String, Object>> jsonList = mapper.readValue(jsonArrayStr, new TypeReference<List<Map<String, Object>>>() {}); Map<Integer, Map<String, Object>> resultMap = new HashMap<>(); for (int i = 0; i < jsonList.size(); i++) { resultMap.put(i, jsonList.get(i)); } return resultMap; }
- Python:
import json def array_to_map_by_index(json_array_str): json_list = json.loads(json_array_str) return {idx: item for idx, item in enumerate(json_list)}
方案2:用对象中的唯一字段作为Map的key
如果数组里的每个对象都有唯一标识(比如id字段),可以用它作为key:
- Java:
public Map<String, Map<String, Object>> arrayToMapByUniqueKey(String jsonArrayStr) throws Exception { ObjectMapper mapper = new ObjectMapper(); List<Map<String, Object>> jsonList = mapper.readValue(jsonArrayStr, new TypeReference<List<Map<String, Object>>>() {}); Map<String, Map<String, Object>> resultMap = new HashMap<>(); for (Map<String, Object> item : jsonList) { String uniqueId = (String) item.get("id"); if (uniqueId != null) { resultMap.put(uniqueId, item); } } return resultMap; }
- Python:
def array_to_map_by_unique_key(json_array_str): json_list = json.loads(json_array_str) result_map = {} for item in json_list: item_id = item.get("id") if item_id is not None: result_map[item_id] = item return result_map
排查小贴士
如果还是解析失败,把解码后的完整字符串打印出来,肉眼检查是否有明显的格式问题——比如有时候网关或代理会额外添加字符,破坏JSON结构。
内容的提问来源于stack exchange,提问作者Cyzanfar
相关产品推荐
相关产品推荐

