You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PR #2151 introduced an override for GenericData.containsKey(Object name) that queries classInfo.hasFieldInfo(fieldName). However, ClassInfo.hasFieldInfo checks only whether the @Key field is declared in class reflection metadata, rather than checking whether the field holds a non-null value on the instance.
Impact & Broken Invariants
In GenericData, declared fields with null values are treated as absent from the map:
keySet() / entrySet() Contradiction:
On new MyData(), containsKey("field") returns true, but get("field") is null, entrySet() has size 0, and keySet().toString() outputs [].
Set.contains vs Iterator Inconsistency:
Because java.util.AbstractMap.keySet().contains(k) delegates to Map.containsKey(k), model.keySet().contains("field") evaluates to true, while iterating over model.keySet() yields 0 elements.
Client Breakages:
Code patterns checking for field presence (such as pagination checks like if (response.containsKey("pageToken"))) now evaluate to true even when the server never populated the field.
Reproduction
publicclassExampleModelextendsGenericData {
@KeyprivateStringoptionalField;
}
ExampleModelmodel = newExampleModel();
// Prior to 2.2.0:// model.containsKey("optionalField") == false// In 2.2.0:model.containsKey("optionalField"); // returns true!model.get("optionalField"); // returns nullmodel.keySet(); // prints []model.keySet().contains("optionalField"); // returns true while iterator is empty
Proposed Fix
In com.google.api.client.util.GenericData.java, check whether the declared field value is non-null, matching DataMap.containsKey():
Activity
chaoren commentedon Aug 28, 2026
Apparently this issue was already pointed out in #2151 (comment)
fix: check field value is non-null in GenericData.containsKey (#2191)