-
Notifications
You must be signed in to change notification settings - Fork 11
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
handling of Unmarshall of multiple files processed in parallel #27
Comments
@marek-kuticka can you share the code or a relevant example? And explain in the example what do you mean by parallel processing, and by provide information to the error handlers |
Good morning I have managed to implement this, below see the patch.
decoder struct has received a fileName, and it is passed from the Unmarshall function, way down to the call to the handler. code, which does the parallel processing is:
with multiple handler functions as follows:
issue was, that if handler, shown in last code piece above has no information about the file name, there is no option to find out later. this is only a quick change, probably better would be to just take file name as parameter and read it into bytes within Unmarshall. Marek |
or.. include it maybe in options? ... marshmallow.WithFileName(...) instead of a direct parameter within Unmarshall func |
@marek-kuticka func processFile(file string) {
v, err := os.ReadFile(file) //read the content of file
if err != nil {
panic(err)
}
prod := Product{file: file}
_, err = marshmallow.Unmarshal(file, v, &prod, marshmallow.WithExcludeKnownFieldsFromMap(true))
if err != nil {
return
}
for e := range prod.errors {
logError(e)
}
}
type Product struct {
// ...
file string
errors []string
}
func (p *Product) HandleJSONData(data map[string]interface{}) {
for key := range data {
p.errors = append(p.errors, fmt.Sprintf("for Product: unknown field in json: %s", key), p.file))
}
} You can achieve that with the current API of Marshmallow. type JSONDataHandler interface {
HandleJSONData(data map[string]interface{})
}
type JSONDataHandlerWithError interface {
HandleJSONData(data map[string]interface{}) error
} if the second one is implemented and returns an error we can propagate it back to the func processFile(file string) {
v, err := os.ReadFile(file) //read the content of file
if err != nil {
panic(err)
}
var prod Product
_, err = marshmallow.Unmarshal(file, v, &prod, marshmallow.WithExcludeKnownFieldsFromMap(true))
if err != nil {
logError(err, file)
}
}
func (p *Product) HandleJSONData(data map[string]interface{}) error {
var err error
for key := range data {
err = errors.Join(err, fmt.Errorf("for Product: unknown field in json: %s", key))
}
return err
} If the first one looks sufficient - go for it. |
I'd have to look into this, as... I think your suggestions works only in case, that we report all levels to top level structure, as discussed in previous issue. However, if the structure of JSON files is much more complicated, and I have approx 15 structures, and thus 15 handler methods, so I have to check, if it works as you suggested |
Still possible, add an @marek-kuticka let me know if you want to try implementing the second option, if not, i think i can get to it early next week |
So.. Bind the "name" to the Product, thus not needed to put it into Decoder.. Then traverse All to collect errors and bind them to product itself? Should be feasible. Not sure I understood fully the 2nd Option. I would maybe try to implement this, would probably need some more details. Thx. Marek |
Go for the first. |
@marek-kuticka v1.1.5 is released with support for reporting errors from func processFile(file string) {
v, err := os.ReadFile(file) //read the content of file
if err != nil {
panic(err)
}
var prod Product
_, err = marshmallow.Unmarshal(file, v, &prod, marshmallow.WithExcludeKnownFieldsFromMap(true))
if err != nil {
// all errors returned from any nested `HandleJSONData` function call will be available here.
// if more than one `HandleJSONData` call returned an error it will be available as a marshmallow.MultipleLexerError
// play with it to get a grip on things
logError(err, file)
}
}
func (p *Product) HandleJSONData(data map[string]interface{}) error {
var err error
for key := range data {
err = errors.Join(err, fmt.Errorf("for Product: unknown field in json: %s", key))
}
return err
} |
as mentioned in Issue 26
proper solution to report errors from unknown elements is to implement methods for each part of the structure.
question remains, if marshmallow.Unmarshall() is executed in closure, in parallel processing, how can I provide the information to the error handlers, which file is being processed, especiallyt in parallel processing?
thx a lot
The text was updated successfully, but these errors were encountered: