Customize sum type JSON encoding and decoding #23609
Replies: 4 comments
-
Just an idea https://play.vlang.io/p/8ce5492e7b : import json
struct Item {
id string @[omitempty]
name string @[omitempty]
action Action
}
enum Action {
add
update
delete_all
}
fn main() {
println(json.encode_pretty([
Item{ id:'1', name:'item', action:.add },
Item{ id:'1', name:'item1-updated', action:.update },
Item{ action:.delete_all }
]))
}
|
Beta Was this translation helpful? Give feedback.
-
The |
Beta Was this translation helpful? Give feedback.
-
To conform with your last json you could do this: import json
struct Elem {
typ Type @[json:"type"]
value Value @[omitempty]
}
struct Value {
item Item
}
struct Item {
id string
name string
}
enum Type {
add_item
update_item
delete_all_items
}
println(json.encode_pretty([
Elem{ typ:.add_item, value:Value{ item:Item{id:'1', name:'item1'}} },
Elem{ typ:.update_item, value:Value{ item:Item{id:'1', name:'item1-updated'}} },
Elem{ typ:.delete_all_items }
]))
|
Beta Was this translation helpful? Give feedback.
-
Thank you for your replies @jorgeluismireles. I see you suggest using an enum instead of a sum type. Let me expand on my example a bit to better illustrate why I prefer to use a sum type:
struct Item {
id string
name string
}
struct AddItem {
item Item
}
struct UpdateItem {
item Item
}
struct DeleteItem {
id string
}
struct DeleteAllItems {}
type Action = AddItem | UpdateItem | DeleteItem | DeleteAllItems
fn transform_action(action Action) string {
return match action {
AddItem {
'add_item ${action.item.id} ${action.item.name}'
}
UpdateItem {
'update_item ${action.item.id} ${action.item.name}'
}
DeleteItem {
// type error: `DeleteItem` has no field named `item`
'delete_item ${action.item.id}'
}
DeleteAllItems {
'delete_all_items'
}
}
} You can see that matching on the If I were to write this example using the enum pattern, I imagine it would look something like this: module main2
enum ActionType {
add
update
delete
delete_all
}
struct Action {
type ActionType
item Item @[omitempty]
id string @[omitempty]
}
struct Item {
id string
name string
}
fn transform_action(action Action) string {
return match action.type {
.add {
'add_item ${action.item.id} ${action.item.name}'
}
.update {
'update_item ${action.item.id} ${action.item.name}'
}
.delete {
// no type error!
'delete_item ${action.item.id}'
}
.delete_all {
'delete_all_items'
}
}
} And in this case since Thus my choice of using sum types as runtime representation, and my original question of being able to customize its JSON encoding/decoding. |
Beta Was this translation helpful? Give feedback.
-
Is there a way to customize the JSON encoding/decoding of sum types?
Here is a simplified example of what I'm working with:
This outputs:
What if I'd like the "tag" property to be
"type"
instead of"_type"
, and the tag values to be snake case (ex:"add_item"
instead of"AddItem"
)? To my knowledge that is not possible at the moment in V.In Rust, using Serde's different enum representations, I can specify the attribute arguments
tag
andrename_all
as follows:Which would produce the desired JSON format:
Another use-case would be wanting to use the "adjacently tagged" format instead of the "internally tagged" format that is currently produced by V.
Again using Rust as an example, I can add the Serde attribute argument
content
:Which would produce:
One of the reason I'm asking is it would make working with existing APIs that use these formats to represent sum types (or discriminated unions) easier?
Beta Was this translation helpful? Give feedback.
All reactions