Java中为无引号JS对象添加引号转换为合法JSON的方案
解决非标准JS类JSON格式转合法JSON的问题
这种非标准的类JSON格式(键无引号、字符串值丢失引号)确实挺闹心的,我之前处理过类似场景,给你几个实用的最优方案,从简单到健壮排序:
方案1:正则表达式快速转换(适合格式规整的场景)
如果你的输入格式相对固定(比如字符串值不含逗号、}、]这类分隔符),正则是最快的解决方式。核心思路分两步:给所有键添加双引号,再给未被引号包裹的字符串值补上双引号。
import java.util.regex.Matcher; import java.util.regex.Pattern; public class NonStandardJsonConverter { public static String convertToValidJson(String invalidInput) { // 第一步:匹配所有"键="的模式,替换为"键": Pattern keyPattern = Pattern.compile("(\\w+)\\s*="); Matcher keyMatcher = keyPattern.matcher(invalidInput); String step1Result = keyMatcher.replaceAll("\"$1\":"); // 第二步:匹配"= 字符串值"的模式(字符串值以字母/下划线开头,非数字、布尔值、括号),给值加引号 Pattern valuePattern = Pattern.compile(":\\s*([a-zA-Z_][a-zA-Z0-9_]*)(?=\\s*(,|}|\\]))"); Matcher valueMatcher = valuePattern.matcher(step1Result); return valueMatcher.replaceAll(":\"$1\""); } public static void main(String[] args) { String invalidJson = "{ ok=true, data= { key1=1.0, key2= [ 1.5, 1.5, 1.5 ], key3= [ { ts=1.526552846892E12, msg=random_message }, { ts=1.526552846892E12, msg=random_message } ] } }"; String validJson = convertToValidJson(invalidJson); System.out.println(validJson); } }
注意:如果你的字符串值里包含逗号、}、]这类分隔符,正则会误判,这种情况就不适合用这个方案了。
方案2:利用JS引擎解析(最健壮的通用方案)
因为你的输入本质是合法的JS对象语法,直接用Java内置的JS引擎来解析,再通过JSON.stringify转成标准JSON,这是最省心、健壮性最高的方案,几乎能处理所有合法JS对象场景,包括带特殊字符的字符串值。
import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; public class NonStandardJsonConverter { public static String convertViaJsEngine(String invalidInput) throws ScriptException { ScriptEngineManager engineManager = new ScriptEngineManager(); ScriptEngine jsEngine = engineManager.getEngineByName("JavaScript"); // 将输入包裹成JS代码,调用JSON.stringify转换 String jsCode = "JSON.stringify(" + invalidInput + ")"; return (String) jsEngine.eval(jsCode); } public static void main(String[] args) throws ScriptException { String invalidJson = "{ ok=true, data= { key1=1.0, key2= [ 1.5, 1.5, 1.5 ], key3= [ { ts=1.526552846892E12, msg=random_message }, { ts=1.526552846892E12, msg=random_message } ] } }"; String validJson = convertViaJsEngine(invalidJson); System.out.println(validJson); } }
优势:不用考虑各种边界情况,JS引擎原生支持这种对象语法,3万字符的量级完全能轻松处理,性能也不会有问题。
方案3:自定义解析器(极端复杂场景可选)
如果前两种方案都满足不了你的特殊需求(比如输入有大量非标准语法),可以自己写一个简单的词法分析器,逐个字符遍历处理:
- 识别键的起始和结束(从字母/下划线到
=),给键包裹双引号并替换=为: - 识别
=后的内容,如果不是数字、true/false、{/[,就把直到下一个分隔符(,/}/])的内容包裹双引号
不过这个方案实现起来比较繁琐,一般前两种方案就足够覆盖绝大多数场景了。
总结
优先推荐方案2(JS引擎解析),因为它的健壮性最高,代码也最简洁;如果你的输入格式完全固定且对性能要求极高,再考虑方案1的正则方式。
内容的提问来源于stack exchange,提问作者SpykeRel04D
相关产品推荐
相关产品推荐

