{"record":{"id":"16a559d93a33edc0","repo":"HMCL-dev/HMCL","slug":"localized-text-cannot-be-empty-object","errorCode":null,"errorMessage":"Localized text cannot be empty object","messagePattern":"Localized text cannot be empty object","errorType":"exception","errorClass":"JsonParseException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/util/i18n/LocalizedText.java","lineNumber":60,"sourceCode":"@JsonSerializable\npublic final class LocalizedText {\n\n    /// Parses a localized text value from a JSON element.\n    ///\n    /// `null` and JSON `null` are treated as absent text. JSON primitives are converted to plain text with\n    /// [JsonPrimitive#getAsString()], and JSON objects are parsed as localized values keyed by language tags.\n    ///\n    /// @param element the JSON element to parse, or `null`\n    /// @return the parsed localized text, or `null` if `element` is absent\n    /// @throws JsonParseException if the element is not a primitive or object, the object is empty, or an object entry\n    ///                            is not a primitive value\n    public static @Nullable LocalizedText fromJson(@Nullable JsonElement element) throws JsonParseException {\n        if (element == null || element instanceof JsonNull)\n            return null;\n\n        if (element instanceof JsonObject jsonObject) {\n            if (jsonObject.isEmpty()) {\n                throw new JsonParseException(\"Localized text cannot be empty object\");\n            }\n\n            var map = new LinkedHashMap<String, String>();\n            jsonObject.asMap().forEach((k, v) -> {\n                if (v instanceof JsonPrimitive primitive) {\n                    map.put(k, primitive.getAsString());\n                } else {\n                    throw new JsonParseException(\"Localized text entry cannot be \" + v.getClass());\n                }\n            });\n            return new LocalizedText(map);\n        }\n\n        if (element instanceof JsonPrimitive primitive) {\n            return new LocalizedText(primitive.getAsString());\n        }\n\n        throw new JsonParseException(\"Unexpected json element: \" + element);","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/util/i18n/LocalizedText.java#L42-L78","documentation":"LocalizedText.fromJson parses a JSON element into a locale-to-string map. An empty JSON object ({}) carries no text in any language, so the method deliberately rejects it with a JsonParseException rather than producing an empty LocalizedText.","triggerScenarios":"Calling LocalizedText.fromJson with a JsonElement that is an empty JsonObject — e.g. a field set to {} in config or downloaded JSON data.","commonSituations":"Serializers or editors emitting {} as a placeholder for an unset localized value; migration scripts wiping translation entries but leaving the empty object.","solutions":["Provide at least one locale key with a string value in the JSON object.","Use JSON null (or omit the field) if the localized value is intentionally absent, which fromJson maps to null.","Sanitize input before parsing: convert empty objects to null ahead of the call."],"exampleFix":"// before\n{\"name\": {}}\n\n// after\n{\"name\": {\"en\": \"Default Name\"}}\n// or, if absent: {\"name\": null}","handlingStrategy":"validation","validationCode":"if (el != null && el.isJsonObject() && el.getAsJsonObject().size() == 0) return null; // treat {} as absent","typeGuard":"static boolean isUsableLocalizedText(@Nullable JsonElement el) { return el == null || el.isJsonNull() || (el.isJsonObject() && !el.getAsJsonObject().isEmpty()) || el.isJsonPrimitive(); }","tryCatchPattern":"try { return LocalizedText.fromJson(el); } catch (JsonParseException e) { log.warn(\"Bad localized text\", e); return null; }","preventionTips":["Emit null instead of {} for absent localized values.","Ensure serializers never write empty objects for LocalizedText fields.","Sanitize external JSON before parsing."],"tags":["json","i18n","validation","empty-value"],"backgroundTag":"empty-required-field","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}