如何定义Data Class使Moshi序列化出指定JSON结构?
formValues Object The issue you're hitting comes down to two key quirks with Moshi's default behavior:
- Moshi doesn't serialize classes with no properties (your
FormValuesis an empty class), so it gets completely omitted from the output JSON. - Your
formValuesproperty is declared as a class member instead of part of the primary constructor, which can make Moshi's code generator overlook it (even with the@Jsonannotation, the empty class problem is the bigger blocker here).
Here are a few clean, practical solutions to get your desired JSON structure {"id":"abcdef","formValues":{}}:
Solution 1: Replace FormValues with an Empty Map (Simplest Approach)
If you don't strictly need a dedicated FormValues class, swapping it for an empty Map is the fastest way to get the empty object in your output:
@JsonClass(generateAdapter = true) class MyDataClass( @Json(name = "id") val id: String, @Json(name = "formValues") val formValues: Map<String, Any?> = emptyMap() )
When serialized, Moshi automatically converts the empty Map to {} in JSON, giving you exactly the structure you want without extra code.
Solution 2: Add a Custom JsonAdapter for FormValues
If you need to keep the FormValues class for your code structure, create a custom adapter to force Moshi to serialize it as an empty object:
First, define the adapter:
class FormValuesAdapter { @ToJson fun serialize(writer: JsonWriter) { // Explicitly write an empty JSON object writer.beginObject().endObject() } @FromJson fun deserialize(reader: JsonReader): FormValues { // Skip the empty object during deserialization reader.beginObject() reader.endObject() return FormValues() } }
Then update MyDataClass to include formValues in the primary constructor (this ensures Moshi's generator reliably picks it up):
@JsonClass(generateAdapter = true) class MyDataClass( @Json(name = "id") val id: String, @Json(name = "formValues") val formValues: FormValues = FormValues() ) { @JsonClass(generateAdapter = true) class FormValues }
Finally, register the adapter when building your Moshi instance:
val moshi = Moshi.Builder() .add(FormValuesAdapter()) .build() val json = moshi.adapter(MyDataClass::class.java).toJson(MyDataClass("abcdef")) // Output: {"id":"abcdef","formValues":{}}
Solution 3: Add a Dummy Property to FormValues (Quick Hack)
For a minimal change without writing a custom adapter, add a hidden dummy property to FormValues to trick Moshi into serializing it as an object:
@JsonClass(generateAdapter = true) class MyDataClass( @Json(name = "id") val id: String, @Json(name = "formValues") val formValues: FormValues = FormValues() ) { @JsonClass(generateAdapter = true) class FormValues { // Dummy property to force Moshi to recognize this as a serializable class @Json(ignore = true) private val placeholder: Unit? = null } }
This works because Moshi now sees FormValues as a class with properties (even though the only one is ignored) and will serialize it as an empty object {}.
内容的提问来源于stack exchange,提问作者Egis

