Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Need Help with CustomMarshaler #410

Open
cpunion opened this issue Nov 28, 2023 · 1 comment
Open

Need Help with CustomMarshaler #410

cpunion opened this issue Nov 28, 2023 · 1 comment

Comments

@cpunion
Copy link

cpunion commented Nov 28, 2023

Hello,

I'm working with a data structure, which is intended to be flexible and may represent various user-defined structures. Here's an example structure:

type A struct {
  ID int
  X, Y int
  Dependent *A
  Children []*A
}

a := &A{
  ID: 1,
  X: 1,
  Y: 2,
}

b := &A{
  ID: 2,
  X: 3,
  Y: 4,
}

c := &A{
  ID: 3,
  X: 5,
  Y: 6,
  Children: []*A{
    a,
  },
  Dependent: &A{
    ID: 4,
    X: 7,
    Y: 8,
    Dependent: &A{
      ID: 5,
      X: 9,
      Y: 10,
    },
  },
}

I need to serialize this tree structure in a flattened structure, all references to objects only store their type/id. For example:

- type: a
  id: 3
  x: 5
  y: 6
  children:
    - type: a
      id: 1
  dependent:
    type: a
    id: 4
- type: a
  id: 4
  x: 7
  y: 8
  dependent:
    type: a
    id: 5
- type: a
  id: 5
  x: 9
  y: 10
- type: a
  id: 1
  x: 1
  y: 2
- type: a
  id: 2
  x: 3
  y: 4

I have been using the CustomMarshaler. My goal is to serialize the first-level objects normally, but for nested objects, return only type/id and queue them for delayed serialization. The challenge is to determine within the CustomMarshaler when an object is at the first level (i.e., the initial call of MarshalWithOptions to our CustomMarshaler) to serialize its simple fields (not sure how to accomplish this), while returning type/id for referenced fields.

Could anyone provide insights or approaches for handling this situation? Any help on how to effectively implement this type of serialization would be greatly appreciated.

Thank you!

@cpunion
Copy link
Author

cpunion commented Nov 28, 2023

Currently, I have replaced the types of Dependency and Children in my structure with the IComponent interface, and it seems to be working well. This change allows CustomMarshaler[ []IComponent ] and CustomMarshaler[IComponent] to handle the lazy serialization of the Children and Dependency fields. Meanwhile, the real type A is being marshaled using reflection. However, if all types are the actual type A, the outcome is either entirely returning type/id for each or serializing them all.

I need a CustomMarshaler like this:

func Serialize(a any) ([]byte, error) {
        encodeOption := yaml.CustomMarshaler(func(a *A) ([]byte, error) {
	        if a == currentRootObject {
		        // FIXME: this line will cause infinite recursion
		        return yaml.MarshalWithOptions(a, encodeOption)
	        } else {
		        return yaml.Marshal(&RefObject{
			        Type: "A",
			        Id: a.ID,
		        })
	        }
        })
        return yaml.MarshalWithOptions(a, encodeOption)
}

@cpunion cpunion changed the title Need Help with Advanced Custom Serialization Need Help with CustomMarshaler Nov 28, 2023
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

No branches or pull requests

1 participant