Skip to content

feat(decoder-configs): add flag to force decoding nil input in decoder config - #42

Merged
sagikazarmark merged 27 commits into
go-viper:mainfrom
mahadzaryab1:zero-values
Sep 20, 2024
Merged

sagikazarmark merged 27 commits into
go-viper:mainfrom
mahadzaryab1:zero-values

Conversation

@mahadzaryab1

@mahadzaryab1 mahadzaryab1 commented Aug 24, 2024 •

Copy link
Copy Markdown

Added a config flag DecodeNil to allow DecodeHook to allow decoding nil inputs. This PR fixes #37.

Comment thread mapstructure.go Resolved
@mahadzaryab1

Copy link
Copy Markdown
Author

@yurishkuro thanks for the feedback! i addressed your comments - let me know if you have any other feedback!

Comment thread mapstructure.go Resolved
Comment thread mapstructure_test.go Resolved
@mahadzaryab1

Copy link
Copy Markdown
Author

@yurishkuro Thanks for your great feedback! I tried to address all your comments. Let me know what you think and when we should open this up for maintainer review.

Comment thread mapstructure.go Resolved
Comment thread mapstructure.go Resolved
Comment thread mapstructure_test.go Resolved
Comment thread mapstructure_test.go Resolved
Comment thread mapstructure.go Resolved
@mahadzaryab1 mahadzaryab1 changed the title [WIP] feat(decoder-configs): add flag to force decoding in decoder config [WIP] feat(decoder-configs): add flag to force decoding nil input in decoder config Aug 27, 2024
@mahadzaryab1

mahadzaryab1 commented Aug 27, 2024 •

Copy link
Copy Markdown
Author

@yurishkuro addressed all your feedback! thank you so much for your comments - should we open it for maintainer review?

Comment thread mapstructure.go Resolved
Comment thread mapstructure_test.go Resolved

@yurishkuro yurishkuro left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm. Just a few nits, otherwise I think it's ready for maintainers' review

Comment thread mapstructure_test.go Resolved
Comment thread mapstructure_test.go Resolved
Comment thread mapstructure_test.go Resolved
@mahadzaryab1 mahadzaryab1 changed the title [WIP] feat(decoder-configs): add flag to force decoding nil input in decoder config feat(decoder-configs): add flag to force decoding nil input in decoder config Aug 27, 2024
@mahadzaryab1
mahadzaryab1 marked this pull request as ready for review August 27, 2024 23:39
Comment thread mapstructure_test.go
decodeNil: true,
input: map[string]interface{}{"message": "bar"},
decodeHook: goodbyeHook,
expectedResult: Transformed{Message: "goodbye"},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this the correct result? It looks like the decode hook has the final say, rather than the actual input.

@mahadzaryab1 mahadzaryab1 Sep 7, 2024 •

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way we have it set up right now is if DecodeNil is true then it will force the hook to run regardless of what the input is. I believe this is what the current behaviour is even without DecodeNil.

Comment thread mapstructure_test.go
decodeNil: false,
input: map[string]interface{}{"message": "bar"},
decodeHook: goodbyeHook,
expectedResult: Transformed{Message: "goodbye"},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one seems okay to me since decodeNil is false so we just run the hook on the input as usual. Let me know if I'm misunderstanding something though.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it just doesn't match my understanding of the hooks - in OTEL Collector the hooks are used to provide defaults, but then the regular parsing still takes place. Perhaps it's specific to how the OTEL hooks are implemented, but looking at mapstructure.go L493, even after the hook is invoked the execution still continues, so should't the parsing of user input still happen?

@mahadzaryab1 mahadzaryab1 Sep 8, 2024 •

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yurishkuro Correct me if I'm wrong but it looks like the input gets overridden by the return value of the hook and then the processing continues on that instead of the original input?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I think that's a valid use case to completely replace the input, but based on the documentation the intention of the hook function is to alter the input somehow, not completely replace it. Because if you completely replace it, especially with the actual struct, then the decoding becomes trivial - just assign input to output, whereas the value of this library is in decoding complex structures.

I would suggest adding another test with a new hook where instead of returning a struct, the hook adds another value to the map, e.g.

map[string]any{"message": originalvalue, "when": "see you later"},

this way you can say that yes the hook was run, but it didn't just short-circuit everything, it still proceeded with the normal decoding.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yurishkuro thanks for the suggestion! i added a few more test cases in. let me know what you think!

Signed-off-by: Mahad Zaryab <mahadzaryab1@gmail.com>
Signed-off-by: Mahad Zaryab <mahadzaryab1@gmail.com>
Comment thread mapstructure_test.go Resolved

@yurishkuro yurishkuro left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Signed-off-by: Mahad Zaryab <mahadzaryab1@gmail.com>

@sagikazarmark sagikazarmark left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @mahadzaryab1 !

@sagikazarmark
sagikazarmark merged commit ff5d967 into go-viper:main Sep 20, 2024
@sagikazarmark sagikazarmark added this to the v2.2.0 milestone Sep 20, 2024
@yurishkuro

Copy link
Copy Markdown

🎉 🎉 🎉

Comment thread mapstructure.go
// If we get here, we have an untyped nil so the type of the input is assumed.
// We do this because all subsequent code requires a valid value for inputVal.
var mapVal map[string]interface{}
inputVal = reflect.MakeMap(reflect.TypeOf(mapVal))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mahadzaryab1 I was previously concerned with this line since we're setting the input to a map when the destination field could be a primitive field. I noticed a bunch of unit tests in OTEL Collector started failing if I enable DecodeNil=true because of this open-telemetry/opentelemetry-collector#10260

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yurishkuro I see. The tests that are failing have a different output kind from a map[string]any. One thing that fixes these tests is simply setting outputVal=inputVal which would remove the assumption of what an input should be and assume that it is the type as the output. However, this doesn't work for the new optional config we added since we expect everything going through this hook here to be a map[string]any, so the Unmarshal method never runs. Is there anything we can do in this hook to force the unmarshaller to run? The other option here would be to specify what type the input is when it is nil. Let me know what you think.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may have a fix, testing it out

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good! let me know if i can help with anything

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#45

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

Successfully merging this pull request may close these issues.

Allow DecodeHook to run for zero values

3 participants