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

Pass s::CS to all usage of lower for dispatch #335

Open
Teo-ShaoWei opened this issue Jan 24, 2022 · 2 comments
Open

Pass s::CS to all usage of lower for dispatch #335

Teo-ShaoWei opened this issue Jan 24, 2022 · 2 comments

Comments

@Teo-ShaoWei
Copy link

I would like to propose for us to pass s::CommonSerialization to all usage of lower. This is so our custom serialization can also dispatch on the catch-all lower(x).

For example, the catch-all lower will become:

function lower(s::CS, a)
    if nfields(a) > 0
        JSON.Writer.CompositeTypeWrapper(a)
    else
        error("Cannot serialize type $(typeof(a))")
    end
end

Context

I am trying to use JSON.jl to create a JSON logger, and I am met with the problem that modules and no-field objects (especially Ptr{Nothing} cannot be logged. This resulted in a fallback to the console logger. Because our office enforce standardization of all logs in JSON format, these console logs get ignored, and so we are not alerted by errors!

I started out by defining lower(::Ptr{Nothing}), but this doesn't solve the bigger picture problem: There might one day be error logs that is not captured as it is not in JSON.

To resolve this, I could quite easily subtype CommonSerialization as the behavior is mainly identical. I just need something like:

function lower(a)
    if nfields(a) > 0
        JSON.Writer.CompositeTypeWrapper(a)
    else
        sprint(show, a)
    end
end

But this is type piracy and resulted in a nasty warning everything we run our code, not a good habit imo. The way I ended up doing it without type piracy warning needed me to duplicate most of lower and show_json within my package.

If lower takes in the serialization and show_json calls it as such, then I can define my own serialization S and have

function lower(s::S, a)
    if nfields(a) > 0
        JSON.Writer.CompositeTypeWrapper(a)
    else
        sprint(show, a)
    end
end

I think this is aligned with the rationale of creating the serialization type in the first place.

additional benefit

The code currently need a hack to handle enum printing as string. This is needed because user cannot define their own lower(x::Enum) without incurring a type piracy warning.

So with this change we can do away with that, and have:

show_json(io::SC, s::CS, x::Enum) = show_json(io, s, lower(s, x))

Then the show_json for strings will be clean and efficient, while that for enum fully demonstrate the necessary detour.

call to action

Let me know if we like this suggestion? Needs be I can perform the code change, just let me know that we are interested to have this 🙏

@fredrikekre
Copy link
Contributor

I am trying to use JSON.jl to create a JSON logger

Unrelated to the issue here in JSON.jl, but have you seen https://github.com/JuliaLogging/LoggingFormats.jl#json-output-log-events-as-json ? I don't think the implementation there has the problem you are describing.

@Teo-ShaoWei
Copy link
Author

Thanks, @fredrikekre for the suggestion! 🙏 I had some issue with JSON3.jl's pretty-printing sometime back, so we haven't considered moving to it. I would be interested to give it a good look again when there's ROI, e.g. for the next project, or if our current JSON logger is proven inadequate.

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

2 participants