Skip to content

feat(json): allow @JsonWriter on enum instance method and property getter#705

Open
dsudomoin wants to merge 1 commit into
kora-projects:1.0from
dsudomoin:feature/json-enum-jsonwriter-instance-getter
Open

feat(json): allow @JsonWriter on enum instance method and property getter#705
dsudomoin wants to merge 1 commit into
kora-projects:1.0from
dsudomoin:feature/json-enum-jsonwriter-instance-getter

Conversation

@dsudomoin

Copy link
Copy Markdown

Motivation

Enum @JsonWriter (from #701) required the value extractor to be a static method — a Kotlin companion object function (or Java public static) taking the enum and returning the JSON value. Putting @JsonWriter on a plain instance method produced a hard must be static error, and there was no property-level form. This PR broadens the accepted shapes so the common cases read naturally.

What changed

@JsonWriter on an enum now additionally accepts:

  • instance method@JsonWriter fun jsonValue(): V (0 params), including @JsonWriter override fun toString(): V;
  • Kotlin property getter@get:JsonWriter val value: V (KSP only; Java has no property concept).

The static (companion) form is unchanged and validated exactly as before. The forms are disambiguated by parameter count:

form shape
static (companion / public static) exactly 1 param of the enum type
instance method 0 params
Kotlin property getter @get: on the property

Value-source priority is unchanged: @JsonWriter (any form) → @Json getter → toString.

Examples

enum class AssetType(val value: String) {
    CURRENCY("currency"), OTHER("other");

    // any one of these now works:
    @JsonWriter fun toValue(): String = value               // instance method
    // @JsonWriter override fun toString(): String = value   // toString override
    // companion { @JsonWriter fun toValue(t: AssetType) = t.value }  // static (as before)
}

// property getter form:
enum class AssetType2(@get:JsonWriter val value: String) { A("a"), B("b") }

Note: a bare @JsonWriter val value (no use-site target) is still rejected by the Kotlin compiler, because @JsonWriter is @Target({TYPE, METHOD}) — use @get:JsonWriter.

Implementation

No runtime change — the generated writer still delegates to EnumJsonWriter<T,V>; only the extractor code block and the value type change.

  • KSP EnumJsonWriterGenerator.detectWriterMethod: accepts body methods and getter-annotated properties in addition to companion methods. An instance member is emitted as Enum::member (a (Enum) -> V), the static one as { e -> Enum.m(e) }.
  • KSP JsonSymbolProcessor: triggers writer generation for a @get:JsonWriter property, handling both KSPropertyDeclaration and KSPropertyGetter (the symbol reported by getSymbolsWithAnnotation for a @get: target varies by KSP version).
  • APT EnumWriterGenerator.detectWriterMethod: accepts instance methods; the existing Enum::method codegen already resolves to Function<Enum,V> for both static and instance forms, so generateEnumWriter is untouched. (Property getters are Kotlin-only, so APT stays method-only.)

Tests

Added to EnumTest (KSP + APT), covering: instance method, toString override, property getter (with and without @Json, to exercise the generation trigger), the from-extension path, and negative cases (instance method with params → no parameters; non-public → must be public). Full :json:json-symbol-processor:test and :json:json-annotation-processor:test are green.

…tter

Previously an enum's @JsonWriter value extractor had to be a static method (Kotlin companion object / Java public static) taking the enum and returning the JSON value. This extends the supported forms: an instance method `@JsonWriter fun jsonValue(): V` (0 params, including `@JsonWriter override fun toString()`), and a Kotlin property getter `@get:JsonWriter val value: V` (KSP only - Java has no property concept).

The static (companion) form is unchanged and still validated; the two method forms are disambiguated by parameter count (static: 1 param of the enum type; instance: 0 params). Generated code references an instance member as Enum::member (a (Enum) -> V function), the static one via a { e -> Enum.m(e) } lambda - no runtime EnumJsonWriter change.

KSP: EnumJsonWriterGenerator.detectWriterMethod now accepts body methods and getter-annotated properties; JsonSymbolProcessor triggers writer generation for a @get:JsonWriter property (handling both KSPropertyDeclaration and KSPropertyGetter, since the reported symbol varies by KSP version). APT: EnumWriterGenerator.detectWriterMethod accepts instance methods; the Enum::method codegen already resolves to Function<Enum,V> for both static and instance forms.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant