binarywang/WxJava · error · JsonParseException
No button array found in menu JSON
Error message
No button array found in menu JSON
What it means
Thrown by WxMenuGsonAdapter.deserialize when the menu JSON contains neither a 'menu' object with a 'button' array nor a top-level 'button' array. The adapter looks under FIELD_MENU then FIELD_BUTTON and, finding neither, raises a JsonParseException rather than returning an empty menu.
Source
Thrown at weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxMenuGsonAdapter.java:106
private void addPropertyIfNotNull(JsonObject obj, String key, String value) {
if (value != null) {
obj.addProperty(key, value);
}
}
@Override
public WxMenu deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject root = json.getAsJsonObject();
JsonArray buttonsJson = null;
if (root.has(FIELD_MENU)) {
JsonObject menuObj = root.getAsJsonObject(FIELD_MENU);
buttonsJson = menuObj.getAsJsonArray(FIELD_BUTTON);
} else if (root.has(FIELD_BUTTON)) {
buttonsJson = root.getAsJsonArray(FIELD_BUTTON);
}
if (buttonsJson == null) {
throw new JsonParseException("No button array found in menu JSON");
}
return buildMenuFromJson(buttonsJson);
}
protected WxMenu buildMenuFromJson(JsonArray buttonsJson) {
WxMenu menu = new WxMenu();
for (JsonElement btnElem : buttonsJson) {
JsonObject buttonJson = btnElem.getAsJsonObject();
WxMenuButton button = convertFromJson(buttonJson);
menu.getButtons().add(button);
if (buttonJson.has(FIELD_SUB_BUTTON) && buttonJson.get(FIELD_SUB_BUTTON).isJsonArray()) {
JsonArray sub_buttonsJson = buttonJson.getAsJsonArray(FIELD_SUB_BUTTON);
for (JsonElement subBtnElem : sub_buttonsJson) {
button.getSubButtons().add(convertFromJson(subBtnElem.getAsJsonObject()));
}
}
}
return menu;View on GitHub (pinned to 1c43293a3c)
Solutions
- Log the raw JSON being deserialized and confirm it has 'menu.button' or a top-level 'button'.
- Check errcode in the response before calling menu deserialization.
- Update or wrap the JSON so it carries a button array (possibly empty) if you build it manually.
Example fix
// before
WxMenu menu = gson.fromJson(rawResponse, WxMenu.class); // rawResponse is an error body
// after
JsonObject o = GsonParser.parse(rawResponse);
if (o.get(WxConsts.ERR_CODE).getAsInt() != 0) {
throw new WxErrorException(WxError.fromJson(rawResponse));
}
WxMenu menu = gson.fromJson(rawResponse, WxMenu.class); Defensive patterns
Strategy: validation
Validate before calling
JsonObject o = GsonParser.parse(rawResponse);
if (o.get(WxConsts.ERR_CODE) != null && o.get(WxConsts.ERR_CODE).getAsInt() != 0) {
throw new WxErrorException(WxError.fromJson(rawResponse, wxType));
}
boolean hasButton = (o.has("menu") && o.getAsJsonObject("menu").has("button")) || o.has("button");
if (!hasButton) throw new IllegalStateException("menu payload missing button array"); Type guard
static boolean hasButtonArray(JsonElement e) {
JsonObject o = e.getAsJsonObject();
return (o.has("menu") && o.getAsJsonObject("menu").has("button")) || o.has("button");
} Try / catch
try {
WxMenu m = gson.fromJson(raw, WxMenu.class);
} catch (JsonParseException e) {
log.error("menu parse failed; raw={}", raw);
throw e;
} Prevention
- Check errcode before deserializing menu responses.
- Log the raw payload to detect schema drift.
- Build stub menu JSON with a (possibly empty) button array in tests.
When it happens
Trigger: Deserializing a WeChat menu payload that has an unexpected shape (e.g. an error response, a wrapper with a different key, or a menu query that returned an empty/error object), or passing a hand-built JSON missing the button array.
Common situations: Menu get API returned an error object (errcode != 0) that was still fed to the adapter; key renamed in a newer API version; integration test using a stub JSON without a button field.
Related errors
AI-assisted analysis of binarywang/WxJava@1c43293a3c (2026-08-14).
Data as JSON: /api/errors/e9aae7bb9195a536.
Report an issue: GitHub.