What happens when parent and child classes have duplicate field names with JSON operator?
← Code Quality · Ref: Q853
When a class hierarchy uses 'default operator $$' (JSON serialization), property names must be unique across the entire hierarchy. In fact they must be unique in every hierarchy, with or without $$: a child that redeclares a parent's field is E02010 (DUPLICATE_PROPERTY_FIELD). Because of that rule a generated $$ can never meet a duplicate key, so there is no separate JSON error.
WHY UNIQUE NAMES ARE REQUIRED
JSON keys must be unique within an object. If a parent had field 'label' and a child also had field 'label', the JSON output would be ambiguous - and, more fundamentally, the object would hold two fields where the author meant one. EK9 rejects the redeclaration at compile time.
CORRECT PATTERN
Use unique field names across the hierarchy:
defines class BaseConfig as open configName <- "default" default operator ? ExtendedConfig extends BaseConfig priority <- 0 default operator ?
INCORRECT PATTERN
defines class BaseConfig as open label <- "default" default operator ? ExtendedConfig extends BaseConfig label <- "custom" // E02010: duplicate property default operator ?
See Q200 for JSON basics. See Q202 for JSON operator patterns. See Q763 for inheritance depth.
Example
defines module qa.quality.duplicate.json.property defines class <?- Base configuration class with configName field. Uses default operator for JSON serialization. -?> BaseConfig as open configName <- "default" BaseConfig() -> cn as String configName :=: cn operator <=> as pure -> other as BaseConfig <- rtn as Integer: configName <=> other.configName operator #? as pure <- rtn as Integer: #? configName default operator <?- Extended configuration with unique field name 'priority'. Does NOT reuse 'configName', which would be E02010. -?> ExtendedConfig extends BaseConfig priority <- 0 ExtendedConfig() -> cn as String p as Integer super(cn) priority :=: p //Sameness (<=>) is inherited from BaseConfig and sealed; this gives ? $ $$ :=: default operator defines program JsonPropertyDemo() stdout <- Stdout() config <- ExtendedConfig("prod", 10) if config? stdout.println("Config created: " + $config)
Common mistakes
E02010 — Parent BaseConfig already has a field named configName. The child cannot redeclare that name, whatever operators are defaulted. Use a unique field name in the child. See ek9 -h E02010 for details.
Incorrect:
configName <- "custom" ExtendedConfig() -> cn as String p as Integer super(cn) configName :=: cn
Correct:
priority <- 0 ExtendedConfig() -> cn as String p as Integer super(cn) priority :=: p
Other ways to ask this
- Is reusing a parent field name a JSON error in EK9?
- Why does EK9 flag duplicate property names in JSON?
- Can parent and child have the same field name with operator $$?
- How does EK9 prevent ambiguous JSON output?
Coming from another language?
Java: Jackson allows field shadowing (confusing JSON). Python: no compile-time JSON validation. Kotlin: Kotlinx serialization detects some conflicts. Rust: Serde handles field shadowing but can be confusing. Go: encoding/json uses last field wins. EK9: E02010 rejects a redeclared property name at compile time, so duplicate JSON keys cannot arise.
Keywords: duplicate, serialization, JSON, field, property, compile-time, E02010, hierarchy, ambiguous, operator