Skip to content

Conversation

@dschadd
Copy link
Contributor

@dschadd dschadd commented Apr 24, 2023

Items Addressed

  • Issue
  • This feature was intended to allow for json to be passed to Decanter without a custom parser.
  • This feature is intended for PostgreSQL column types of json or jsonb
  • This feature is not intended to accept or "bypass" large json blob data sent over from UI to a Rails JSON API. It is column specific.

Author Checklist

  • Add unit test(s)
  • Update documentation (if necessary)
  • Update version in version.rb following versioning guidelines

module Decanter
module Parser
class JsonParser < ValueParser

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since json is not a native Ruby data type, there is no specific allowed types. Instead all values passed to this parser will be parsed by JSON.parse(val), unless they are nil or blank strings.

class JsonParser < ValueParser

parser do |val, options|
raise Decanter::ParseError.new 'Expects a JSON string' if val.is_a?(Array) || val.is_a?(Hash)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

JSON.parse only accepts string type as an argument

Copy link
Contributor

Choose a reason for hiding this comment

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

Forgive my ignorance here – does ActiveRecord require that the input to create/update is a hash? Or will it accept a serialized JSON string?

Copy link
Contributor

Choose a reason for hiding this comment

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

What's the benefit of checking for an Array or a Hash as opposed to is_a? String?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  1. I'm having a hard time finding exact documentation, but I don't think there is a specific requirement for it to be hash. Mainly because JSON can be an array, hash, string

  2. I think I had it this way just for readability as to avoid unless, but looking at it again I'm not sure that's any more readable. I think I'll change it to unless is_a? String

This line in particular is difficult since JSON can be many things. I almost decided to remove this entirely, but wanted to keep some error message here. I could make an argument for having no error message here, but that felt wrong?

I leaned into the fact the client will send it as a string, I will check that, and then the code on line 8 will parse it to become a JSON object for Rails to use

Copy link
Contributor

Choose a reason for hiding this comment

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

From some quick testing in the console, it looks like JSON.parse throws an error for anything that's not a string (including booleans, integers, etc).

Because of that, to me the most readable option seems like unless is_a? String, but I also wonder if a readable alternative could be rescuing from a JSON.parse error to tell the dev that the value is not valid JSON.

@@ -1,3 +1,3 @@
module Decanter
VERSION = '4.0.1'.freeze
VERSION = '4.0.2'.freeze
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not 100% sure on versioning semantics for minor feature. I suppose this could be 4.1?

Copy link
Contributor

Choose a reason for hiding this comment

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

This is a backwards compatible feature, which warrants a minor bump (i.e., 4.1.0)

@dschadd
Copy link
Contributor Author

dschadd commented Apr 25, 2023

I had trouble updating the versioning for this. I updated version.rb, ran bundle install and pushed and got a fail. Tried it a few different ways with no success. What am I doing wrong?

@dschadd dschadd marked this pull request as ready for review April 25, 2023 17:17
@dschadd dschadd requested a review from chawes13 as a code owner April 25, 2023 17:17
@@ -0,0 +1,12 @@
module Decanter
module Parser
class JsonParser < ValueParser
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe this should inherit from HashParser

See https://github.com/LaunchPadLab/decanter#custom-parser-base-classes

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, that doesn't account for the fact that it could be an array. NVM!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yea it turns out that JSON is anything lol

class JsonParser < ValueParser

parser do |val, options|
raise Decanter::ParseError.new 'Expects a JSON string' if val.is_a?(Array) || val.is_a?(Hash)
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the benefit of checking for an Array or a Hash as opposed to is_a? String?

@nicoledow nicoledow self-requested a review March 7, 2025 14:52
Copy link
Contributor

@nicoledow nicoledow left a comment

Choose a reason for hiding this comment

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

@dschadd Bumping - are you still interested and do you still have capacity to address the comments below to get this into an upcoming release? Aiming for the end of the quarter.

Comment on lines 9 to 25
describe '#parse' do
it 'parses string value and returns a parsed JSON' do
expect(parser.parse(name, '{"key": "value"}')).to match({name => {"key" => "value"}})
end

context 'with empty string' do
it 'returns nil' do
expect(parser.parse(name, '')).to match({name => nil})
end
end

context 'with nil' do
it 'returns nil' do
expect(parser.parse(name, nil)).to match({name => nil})
end
end
end
Copy link
Contributor

Choose a reason for hiding this comment

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

As mentioned here, I'd love to see a descriptive error thrown if the string can't be parsed as valid JSON. I think that would also warrant a test case here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Might also be worth adding test cases to ensure a JSON array string (i.e. '['investment', 'early_retirement', 'saving']') and an object ('{ "first_name": "Daniel", "last_name": "Schadd" }' can both be handled.

@dschadd
Copy link
Contributor Author

dschadd commented Mar 11, 2025

@dschadd Bumping - are you still interested and do you still have capacity to address the comments below to get this into an upcoming release? Aiming for the end of the quarter.

Hey @nicoledow - don't think I'll be able to get to one this quarter, but would be happy to throw this on my Q3 goals?

@nicoledow
Copy link
Contributor

@dschadd Bumping - are you still interested and do you still have capacity to address the comments below to get this into an upcoming release? Aiming for the end of the quarter.

Hey @nicoledow - don't think I'll be able to get to one this quarter, but would be happy to throw this on my Q3 goals?

@dschadd No worries! I just wanted to get an idea of what might be in the Q1 release. Next quarter is great!

@nicoledow nicoledow linked an issue Aug 22, 2025 that may be closed by this pull request
Comment on lines +15 to +39
- [Decanter](#decanter)
- [Migration Guides](#migration-guides)
- [Contents](#contents)
- [Basic Usage](#basic-usage)
- [Decanters](#decanters)
- [Generators](#generators)
- [Decanters](#decanters-1)
- [Parsers](#parsers)
- [Resources](#resources)
- [Decanting Collections](#decanting-collections)
- [Control Over Decanting Collections](#control-over-decanting-collections)
- [Nested resources](#nested-resources)
- [Default parsers](#default-parsers)
- [Parser options](#parser-options)
- [Exceptions](#exceptions)
- [Advanced Usage](#advanced-usage)
- [Custom Parsers](#custom-parsers)
- [Custom parser methods](#custom-parser-methods)
- [Custom parser base classes](#custom-parser-base-classes)
- [Squashing inputs](#squashing-inputs)
- [Chaining parsers](#chaining-parsers)
- [Requiring params](#requiring-params)
- [Default values](#default-values)
- [Global configuration](#global-configuration)
- [Contributing](#contributing)
Copy link
Contributor

Choose a reason for hiding this comment

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

Just formatting

Copy link

@kweingart08 kweingart08 left a comment

Choose a reason for hiding this comment

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

@nicoledow - This looks good to me.

@nicoledow nicoledow merged commit 48763ad into main Aug 29, 2025
6 checks passed
@nicoledow nicoledow deleted the feature/json-parse branch August 29, 2025 19:36
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.

JSON Type Parser

5 participants