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

Added custom json serializer support #40

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

josearomeroj
Copy link

Implemented custom serializer for json: #36

Copy link

@atticus-sullivan atticus-sullivan left a comment

Choose a reason for hiding this comment

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

It's been a while and I'm not sure why no one touched this. All in all I think this looks good, just some inconsistencies and no reason why not to do this for XML as well (but we should rename this PR or do this in another PR).

Marshal(v interface{}) ([]byte, error)
Unmarshall(data []byte, v interface{}) error
NewEncoder(w io.Writer) Encoder
Decode(r io.Reader, v interface{}) error

Choose a reason for hiding this comment

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

Having NewEncoder but no NewDecoder in the Marshaller interface seems a bit inconsistent. I'm not sure which way to go here. I'd propose to either

  1. add a Decoder interface with only a Decode function and NewDecoder() instead of Decode() or
  2. omit the Encoder interface and rely on the Marshaller implementation taking care of configuring the Encoder the right way (for the default we can encoder.SetEscapeHTML(true) in the Encode function).

I think 2. is a bit nicer since configuring the Encoder always needs to take place in the Encode/NewEncoder function if the user provides an own implementation. But I'd be fine with 1. as well.

return json.Unmarshal(data, v)
}

func SetJsonMarshaller(m Marshaller) {

Choose a reason for hiding this comment

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

Looking at Respond and Decode it would maybe be more consistent to simply expose the jsonMarshaller so that it can be set directly.

"io"
)

var jsonMarshaller Marshaller = jsonDefaultMarshaller{}

Choose a reason for hiding this comment

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

Maybe we should add a marshaller for XML as well so that this can be configured as well.

@atticus-sullivan
Copy link

atticus-sullivan commented Apr 6, 2023

[at]Maintainers would be nice if you could comment if this PR has a chance of being merged. My use-case is just to configure the json-decoder (just setting DisallowUnknownFields() to try to detect typos in requests) but right now even such a small adjustment is not possible.

Oh and @josearomeroj would you still work on this PR if the Maintainers want any changes? (otherwise I'd be willing to adopt this PR by cloning and create a new PR)

@josearomeroj
Copy link
Author

Hi @atticus-sullivan, thank you for your feedback.
I have no problem to continue working in this but looks like maintainers are inactive.

@atticus-sullivan
Copy link

Oh nice, that's already the first step. Wasn't sure since almost a whole year passed since you opened this issue.
Well looking at the commits the maintainers are a bit inactive, but from time to time there is work. Not sure if there is a better way of contacting them than writing in comments in the PR. Maybe we can Ping @pkieltyka seems to be the only one in the go-chi organization. According to this comment, this package is still maintained (but I always try not to put too much pressure on maintainers of open source projects as this is free-time and it should feel like it)

Especially in this case not having this feature is a bit sad as looking at other PRs (#34 #33 #39 , I think even #11 would be possible to configure) this feature really helps a lot.

Comment on lines +10 to +15
type Marshaller interface {
Marshal(v interface{}) ([]byte, error)
Unmarshall(data []byte, v interface{}) error
NewEncoder(w io.Writer) Encoder
Decode(r io.Reader, v interface{}) error
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Hi, thanks for your contribution. Few comments:

  1. I feel like this is too big of an interface.
  2. Unmarshall() should be spelled with single l.
  3. I think we'd need to account for this issue: DecodeJSON accepts "{}\n some garbage data" incorrectly #42 and perhaps drop NewEncoder() and NewDecoder() for good.

Choose a reason for hiding this comment

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

  1. Depends on 3. if we want to keep the Decoder/Encoder way of handling data we still need at least marshal (if we want to apply the interface for XML as well, which would make sense)
  2. 👍
  3. Not completely sure but as I see it, not using the Decoder/Encoder requires a double-pass over the data (1. collecting the []byte from the io.reader and 2. later parse the []byte to struct). So in general I'm in favor of using Decoder/Encoder. Nevertheless, if this additional data which goes undetected is a security issue we should definitely avoid it. But that's the point I'm not sure about. Doesn't it help explicitly discarding everything which comes after the parsed JSON object?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, can we please confirm that discard solves the "confused deputy" issue?

Choose a reason for hiding this comment

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

Let's continue this discussion in the respective issue.

Choose a reason for hiding this comment

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

Alright after #42 (comment) I'd personally prefer sticking with Encoder/Decoder checking for EOF after the decoder.Decode() call. If the reader is not at an EOF we just return an error.

What are your opinions on that?

Choose a reason for hiding this comment

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

So I'd be at

type Encoder interface {
	Encode(w io.Writer, r *http.Request, ctx context.Context, v interface{}) (error)
}

type Decoder interface {
	Decode(w io.Reader, r *http.Request, ctx context.Context, v interface{}) (error)
}

if really needed one could pass options with the help of the ctx (but I quite dislike working like that if not necessary). I'm still not quite sure if directly adding the request-object is really needed (I personally have no use-case for this, but also I'm not that experienced in this regard) but if you say that using it is a common case, let's directly include it in the signature.

How do you suggest that we proceed in this subject. Ask @josearomeroj to make the modifications (if there is a willingness to do so) or make a new PR (or something different)?

Copy link
Contributor

Choose a reason for hiding this comment

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

We could reuse the r.Context() from *http.Request

Copy link
Contributor

Choose a reason for hiding this comment

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

I think a new PR would make sense if you don't mind

Choose a reason for hiding this comment

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

We could reuse the r.Context() from *http.Request

Oh I've missed this one.

I think a new PR would make sense if you don't mind

Alright. I'd wait until tomorrow if @josearomeroj responds. If not I'd be willing to work on this.

Copy link
Author

Choose a reason for hiding this comment

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

If you see it clearly, go ahead! I'm going to be busy this week and I won't be able to work on it.

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.

None yet

3 participants