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

Is there a way to marshal de JSON #23

Closed
MrMarble opened this issue Jan 25, 2023 · 6 comments · Fixed by #24
Closed

Is there a way to marshal de JSON #23

MrMarble opened this issue Jan 25, 2023 · 6 comments · Fixed by #24
Assignees
Labels
documentation Improvements or additions to documentation

Comments

@MrMarble
Copy link

Hi!
I am looking for a way to read, modify and save a JSON of which I am only interested in part of its content.
This package looks like it could be useful for the first two steps, but I'm not sure about the last one.

Is there any way to do it? Either through the API of the package or in some recommended way.

Thanks!

(P.S. I tried to open a discussion instead of an issue but I can't do it)

@avivpxi
Copy link
Collaborator

avivpxi commented Jan 25, 2023

@MrMarble marshmallow should be able to help with partial handling of JSON objects.
It does not directly work with file management, on purpose. But this is not an issue as you can always combine marshmallow of os or other interfaces to work with files.

Can you provide more input on what exactly you're trying to achieve?
In terms of reading and writing files, you could do this:

func main() {
	file, err := os.Open("input.json")
	if err != nil {
		panic(err)
	}

	data, err := io.ReadAll(file)
	if err != nil {
		panic(err)
	}

	err = file.Close()
	if err != nil {
		panic(err)
	}

	dataAsStruct := someStruct{}
	dataAsMap, err := marshmallow.Unmarshal(data, &dataAsStruct)
	if err != nil {
		panic(err)
	}

	// process dataAsStruct/dataAsMap

	output, err := json.Marshal(dataAsMap) // note we write back dataAsMap. this depends on your exact use case. also note we use json.Marshal but we can also use json.MarshalIndent(data, "", "\t") if you want to prettify the output
	if err != nil {
		panic(err)
	}

	err = os.WriteFile("output.json", output, 0644)
	if err != nil {
		panic(err)
	}
}

You can share your exact use case and needs to further clarify if marshmallow can help.

@MrMarble
Copy link
Author

MrMarble commented Jan 25, 2023

Ups, I was a little too shallow on my explanation, my bad...

Reading and writing the file is not a problem.

I'm working with Node package.json files, which have a set of determined properties, but any library could add its own configuration to the file, so marshaling the hole file is a no-go. I'm only interested in part of the file, see for example this one:

{
	"name": "my-library",
	"version": "0.0.0",
	"description": "awesome library", // Not interested 
	"dependencies": {
		"react": "^18.0.0",
	},
	"devDependencies": {
		"vite": "^4.0.0"
	}
	"husky": { // Also not interested
		...	
	}
	... // Other properties I don't need
}

With marshmallow, I could have a struct defining the parts I want to read and modify:

type PackageJSON struct {
	Name string
	Version string
	Dependencies map[string]string
	DevDependencies map[string]string
}

The question is, how do I save the file, keeping also the "extra" I don't need in my struct but is needed in the final file

@avivpxi
Copy link
Collaborator

avivpxi commented Jan 25, 2023

Sure! You can. Marshmallow will allow you to work with a PackageJSON instance, and it will also provide a map containing all the data. Eventually you want to write the map data back to file, but before you do you need to work on a selected group of fields. Theoretically, you could do this:

dataAsStruct := PackageJSON{}
dataAsMap, _ := marshmallow.Unmarshal(/* input from file */, &dataAsStruct)
// do stuff with dataAsStruct
out, _ := json.MarshalIndent(dataAsMap, "", "\t")
// write out to file

It will work as expected for values that are pointers. When you change pointer values in the struct, it will also reflect the values in the map which you eventually write out. Note that maps are effectively pointers so if you plan to change Dependencies/DevDependencies it will work fine, but changes done to Name/Version will not be visible.
As I see it you have 3 solutions:

  • Marshal the struct into the map before writing out - this is probably the most maintainable solution out of the three. The downside is that it also has the worse performance since we add the extra marshal + unmarshal steps. This is probably the way to go if performance is not an issue.
  • Work with pointers - force pointer on primitive types. This will be annoying to work with and require a lot of nil checks and pointer arithmetic. On the other hand, it's probably the choice when performance is an important factor.
  • Manually change primitive fields in the map - This kind of bypasses the whole point of marshmallow, but it performs well and does not require pointers so it's probably the way to go if you want many non primitive values and only one, constant primitive field.

@avivpxi
Copy link
Collaborator

avivpxi commented Jan 26, 2023

@MrMarble when you're available, please let us know if it was helpful or maybe there's something actionable here 🙏

@MrMarble
Copy link
Author

@MrMarble when you're available, please let us know if it was helpful or maybe there's something actionable here 🙏

Sorry I was busy at work today.

That's just what I needed! Thank you for your time!
I didn't know that the struct and the map shared the same references, I don't see it in the documentation.

Thank you! (feel free to close the issue)

@avivpxi avivpxi linked a pull request Jan 27, 2023 that will close this issue
@avivpxi avivpxi self-assigned this Jan 27, 2023
@avivpxi avivpxi added the documentation Improvements or additions to documentation label Jan 27, 2023
@avivpxi
Copy link
Collaborator

avivpxi commented Jan 29, 2023

@MrMarble updated the docs accordingly. Thanks for the input.
Let me know how it works out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants