解析含Long类型值的JSON字符串时遇NumberFormatException的解决方法
解决json-simple解析超大数字ID时的NumberFormatException问题
这个异常的核心原因是你的日志里的tweet id(比如16606634614844517897)已经超过了Java Long类型的最大值(9223372036854775807),而json-simple 1.1.1版本在解析数字时默认尝试转成Long,一旦超出范围就会抛出这个错误。
下面给你几个可行的解决办法:
方案1:改用更现代的JSON库(推荐)
json-simple已经多年没有维护,对超大数字的处理支持很差。换成Gson或者Jackson这类主流库,它们对大数值的处理更加灵活,无需额外配置就能避免这个问题。
使用Gson的示例代码:
import com.google.gson.Gson; import com.google.gson.JsonObject; public class JsonParserExample { public static void main(String[] args) { String line = "{\"action\": \"tweet\", \"id\": 16606634614844517897, \"message\": \"woop #ruby\", \"timestamp\": 1487149445603, \"user\": \"hugopeixoto\"}"; Gson gson = new Gson(); JsonObject jsonObject = gson.fromJson(line, JsonObject.class); String user = jsonObject.get("user").getAsString(); System.out.println("User: " + user); } }
使用Jackson的示例代码:
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; public class JsonParserExample { public static void main(String[] args) throws Exception { String line = "{\"action\": \"tweet\", \"id\": 16606634614844517897, \"message\": \"woop #ruby\", \"timestamp\": 1487149445603, \"user\": \"hugopeixoto\"}"; ObjectMapper mapper = new ObjectMapper(); JsonNode jsonNode = mapper.readTree(line); String user = jsonNode.get("user").asText(); System.out.println("User: " + user); } }
方案2:预处理JSON字符串(无需换库)
如果必须继续使用json-simple,可以预处理每行字符串,把超大数字的id字段转换成字符串类型,再进行解析。用正则表达式替换即可:
import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; public class JsonParserExample { public static void main(String[] args) throws Exception { String line = "{\"action\": \"tweet\", \"id\": 16606634614844517897, \"message\": \"woop #ruby\", \"timestamp\": 1487149445603, \"user\": \"hugopeixoto\"}"; // 把"id": 数字 替换为"id": "数字" String processedLine = line.replaceAll("(\"id\":\\s*)(\\d+)", "$1\"$2\""); JSONParser parser = new JSONParser(); JSONObject json = (JSONObject) parser.parse(processedLine); String user = (String) json.get("user"); System.out.println("User: " + user); } }
这个方法的前提是日志中id字段的格式固定,正则能准确匹配到需要替换的内容。
方案3:自定义json-simple的数字解析逻辑(不推荐)
如果你不想换库也不想预处理,那需要修改json-simple的源码或者自定义一个解析器,让它把超出Long范围的数字解析成BigInteger。不过这个方法比较繁琐,而且json-simple已经停止维护,后续可能会有其他问题,所以不优先推荐。
内容的提问来源于stack exchange,提问作者Kushal Shinde
相关产品推荐
相关产品推荐

