Git Product home page Git Product logo

jsonapi-deserializable's Introduction

jsonapi-deserializable's People

Contributors

beauby avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

jsonapi-deserializable's Issues

`hash` is not getting populated?

Hi

I'm working in a little Sinatra app and found that after deserializing with the Resource class defined I here, I can't seem to get to the attributes because the to_h method give me nothing.

The get_jsonapi method was defined elsewhere and does the http call and returns the response data that lives under "data" key.

As you can see, the deserializer properly pulls the attribute out but does not fill the @hash attribute so the to_h doesn't give me any data back.

# in a console

> jsonapi = get_jsonapi("studios/1890-bryant-street-studios.json")
=> {"id"=>"3",
 "type"=>"studio",
 "attributes"=>
  {"name"=>"1890 Bryant Street Studios",
   "street_address"=>"1890 bryant st",
   "city"=>"New Ginaberg",
   "map_url"=>"http://maps.google.com/maps?q=1890+bryant+st%2C+New+Ginaberg%2C+Kansas%2C+87776",
   "url"=>"/studios/1890-bryant-street-studios",
   "slug"=>"1890-bryant-street-studios"},
"relationships"=>{"artists"=>{"meta"=>{"count"=>27}}}}

> studio = JSONAPI::Deserializable::Resource.new(jsonapi)
=> #<JSONAPI::Deserializable::Resource:0x00007fc8663fcab0
 @attributes=
  {"name"=>"1890 Bryant Street Studios",
   "street_address"=>"1890 bryant st",
   "city"=>"New Ginaberg",
   "map_url"=>"http://maps.google.com/maps?q=1890+bryant+st%2C+New+Ginaberg%2C+Kansas%2C+87776",
   "url"=>"/studios/1890-bryant-street-studios",
   "slug"=>"1890-bryant-street-studios"},
 @data=
  {"id"=>"3",
   "type"=>"studio",
   "attributes"=>
    {"name"=>"1890 Bryant Street Studios",
     "street_address"=>"1890 bryant st",
     "city"=>"New Ginaberg",
     "map_url"=>"http://maps.google.com/maps?q=1890+bryant+st%2C+New+Ginaberg%2C+Kansas%2C+87776",
     "url"=>"/studios/1890-bryant-street-studios",
     "slug"=>"1890-bryant-street-studios"},
   "relationships"=>{"artists"=>{"meta"=>{"count"=>27}}}},
 @hash={},
 @id="3",
 @relationships={"artists"=>{"meta"=>{"count"=>27}}},
 @reverse_mapping={},
 @root="/data",
 @type="studio">


> studio.to_h
=> {}

Am I mis-using things? Or is this a bug?

I did a tiny bit of digging and it seems that in resource.rb where you define

      def deserialize_attr(key, val)
        block = self.class.attr_blocks[key] || self.class.default_attr_block
        return {} unless block

the block is actually nil. Is that expected? Am I supposed to define a default_attr_block?

block format for JSONAPI::Deserializable::Resource

Hi

I am trying to use DeserializableResourceType.call() but receiving a {} return value.

I am not sure what the format for the blocks (type, attributes, relationship and id ) in the JSONAPI::Deserializable::Resource would be.

Thank you very much

Deserializing a Resource Object/Relationship on create throws an error when no ID is provided

I'm trying to create a new resource with an existing template relationship and an address relationship that should become a new resource. Example POST request:

{
  "data": {
    "type": "post",
    "attributes": {
      "title": "foo"
    },
    "relationships": {
      "template": {
        "data": {
          "type": "templates",
          "id": "1"
        }
      },
      "address": {
        "data": {
          "type": "addresses",
          "first_name": "John",
          "last_name": "Doe"
        }
      }
    }
  }
}

Because the address relationship does not contain an ID, it throws the following error:

A resource identifier object MUST contain ['id', 'type'] members.

I get that, because the JSON:API documentation clearly states:

A resource object MUST contain at least the following top-level members:
- id
- type

However, the documentation contains an important exception:

Exception: The id member is not required when the resource object originates at the client and represents a new resource to be created on the server.

That's exactly what I'm doing. Can we create an exception for this, or is this is incorrect way?

Relationships and attributes property collision

There is an issue in case payload deserialization like this happens:

{
   "data":{
      "type":"billing_period",
      "attributes":{
         "invoiceType":"prepayment",
         "billingPeriodStart":"2022-06-01",
         "billingPeriodEnd":"2022-07-01",
         "amount":"2000"
      },
      "relationships":{
         "invoice":{
            "data":{
               "type":"invoice",
               "id":"42b2a67b-5c50-4d8f-b91e-e4269933b007"
            }
         }
      }
   }
}

In this case due to hash merging order relationships always take precedence over attributes,
so the deserialized attribute invoiceType in the case above will be invoice instead of expected prepayment.

The fix may be as easy as switching the order for deserialize_rels and deserialize_attrs

        hashes = [deserialize_type, deserialize_id,
                  deserialize_rels, deserialize_attrs]

though it's not backwards compatible.

Please suggest,
Leo

No Docs?

I've been checking back periodically to see if the docs have been written for deserialization, but sadly they haven't.

Any chance even a basic usage of this could be sketched out?

Thanks for your work.

Add configuration for key transforms.

This can currently be achieved by setting a custom default attribute deserialization proc.

JSONAPI::Deserializable.configure do |config|
  config.default_attribute = proc do |key, value|
    { key.capitalize.to_sym => value }
  end
end

App crashes with Rails env as production

Hi,

My app refuses to start when I set Rails.env to production event though it successfully starts when set to development:

  • jsonapi: 0.5.0 (jsonapi-deserializable: 0.2.0)
  • rails: 5.1.4
  • ruby (via rbenv): 2.4.3

Backtrace when I launch the console for example, bundle exec rails console production:

/my_home/my_app/vendor/bundle/gems/jsonapi-deserializable-0.2.0/lib/jsonapi/deserializable/resource/dsl.rb:15:in `type': wrong number of arguments (given 1, expected 0) (ArgumentError)
        from /my_home/my_app/app/deserializers/deserializable_user.rb:2:in `<class:DeserializableUser>'
        from /my_home/my_app/app/deserializers/deserializable_user.rb:1:in `<top (required)>'
        from /my_home/my_app/vendor/bundle/gems/activesupport-5.1.4/lib/active_support/dependencies.rb:476:in `load'
        from /my_home/my_app/vendor/bundle/gems/activesupport-5.1.4/lib/active_support/dependencies.rb:476:in `block in load_file'
        from /my_home/my_app/vendor/bundle/gems/activesupport-5.1.4/lib/active_support/dependencies.rb:661:in `new_constants_in'
        from /my_home/my_app/vendor/bundle/gems/activesupport-5.1.4/lib/active_support/dependencies.rb:475:in `load_file'
        from /my_home/my_app/vendor/bundle/gems/activesupport-5.1.4/lib/active_support/dependencies.rb:374:in `block in require_or_load'
        from /my_home/my_app/vendor/bundle/gems/activesupport-5.1.4/lib/active_support/dependencies.rb:36:in `block in load_interlock'
        from /my_home/my_app/vendor/bundle/gems/activesupport-5.1.4/lib/active_support/dependencies/interlock.rb:12:in `block in loading'
        from /my_home/my_app/vendor/bundle/gems/activesupport-5.1.4/lib/active_support/concurrency/share_lock.rb:149:in `exclusive'
        from /my_home/my_app/vendor/bundle/gems/activesupport-5.1.4/lib/active_support/dependencies/interlock.rb:11:in `loading'
        from /my_home/my_app/vendor/bundle/gems/activesupport-5.1.4/lib/active_support/dependencies.rb:36:in `load_interlock'
        from /my_home/my_app/vendor/bundle/gems/activesupport-5.1.4/lib/active_support/dependencies.rb:357:in `require_or_load'
        from /my_home/my_app/vendor/bundle/gems/activesupport-5.1.4/lib/active_support/dependencies.rb:335:in `depend_on'
        from /my_home/my_app/vendor/bundle/gems/activesupport-5.1.4/lib/active_support/dependencies.rb:251:in `require_dependency'
        from /my_home/my_app/vendor/bundle/gems/railties-5.1.4/lib/rails/engine.rb:476:in `block (2 levels) in eager_load!'
        from /my_home/my_app/vendor/bundle/gems/railties-5.1.4/lib/rails/engine.rb:475:in `each'
        from /my_home/my_app/vendor/bundle/gems/railties-5.1.4/lib/rails/engine.rb:475:in `block in eager_load!'
        from /my_home/my_app/vendor/bundle/gems/railties-5.1.4/lib/rails/engine.rb:473:in `each'
        from /my_home/my_app/vendor/bundle/gems/railties-5.1.4/lib/rails/engine.rb:473:in `eager_load!'
        from /my_home/my_app/vendor/bundle/gems/railties-5.1.4/lib/rails/engine.rb:354:in `eager_load!'
        from /my_home/my_app/vendor/bundle/gems/railties-5.1.4/lib/rails/application/finisher.rb:67:in `each'
        from /my_home/my_app/vendor/bundle/gems/railties-5.1.4/lib/rails/application/finisher.rb:67:in `block in <module:Finisher>'
        from /my_home/my_app/vendor/bundle/gems/railties-5.1.4/lib/rails/initializable.rb:30:in `instance_exec'
        from /my_home/my_app/vendor/bundle/gems/railties-5.1.4/lib/rails/initializable.rb:30:in `run'
        from /my_home/my_app/vendor/bundle/gems/railties-5.1.4/lib/rails/initializable.rb:59:in `block in run_initializers'
        from /my_home/.rbenv/versions/2.4.3/lib/ruby/2.4.0/tsort.rb:228:in `block in tsort_each'
        from /my_home/.rbenv/versions/2.4.3/lib/ruby/2.4.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
        from /my_home/.rbenv/versions/2.4.3/lib/ruby/2.4.0/tsort.rb:431:in `each_strongly_connected_component_from'
        from /my_home/.rbenv/versions/2.4.3/lib/ruby/2.4.0/tsort.rb:349:in `block in each_strongly_connected_component'
        from /my_home/.rbenv/versions/2.4.3/lib/ruby/2.4.0/tsort.rb:347:in `each'
        from /my_home/.rbenv/versions/2.4.3/lib/ruby/2.4.0/tsort.rb:347:in `call'
        from /my_home/.rbenv/versions/2.4.3/lib/ruby/2.4.0/tsort.rb:347:in `each_strongly_connected_component'
        from /my_home/.rbenv/versions/2.4.3/lib/ruby/2.4.0/tsort.rb:226:in `tsort_each'
        from /my_home/.rbenv/versions/2.4.3/lib/ruby/2.4.0/tsort.rb:205:in `tsort_each'
        from /my_home/my_app/vendor/bundle/gems/railties-5.1.4/lib/rails/initializable.rb:58:in `run_initializers'
        from /my_home/my_app/vendor/bundle/gems/railties-5.1.4/lib/rails/application.rb:353:in `initialize!'
        from /my_home/my_app/config/environment.rb:5:in `<top (required)>'
        from /my_home/my_app/vendor/bundle/gems/spring-2.0.2/lib/spring/application.rb:102:in `require'
        from /my_home/my_app/vendor/bundle/gems/spring-2.0.2/lib/spring/application.rb:102:in `preload'
        from /my_home/my_app/vendor/bundle/gems/spring-2.0.2/lib/spring/application.rb:153:in `serve'
        from /my_home/my_app/vendor/bundle/gems/spring-2.0.2/lib/spring/application.rb:141:in `block in run'
        from /my_home/my_app/vendor/bundle/gems/spring-2.0.2/lib/spring/application.rb:135:in `loop'
        from /my_home/my_app/vendor/bundle/gems/spring-2.0.2/lib/spring/application.rb:135:in `run'
        from /my_home/my_app/vendor/bundle/gems/spring-2.0.2/lib/spring/application/boot.rb:19:in `<top (required)>'
        from /my_home/.rbenv/versions/2.4.3/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require'
        from /my_home/.rbenv/versions/2.4.3/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require'
        from -e:1:in `<main>'

Culprit:

class DeserializableUser < JSONAPI::Deserializable::Resource
  type 'users'

  attributes :first_name, :last_name, :identifier, :email
end 

Any idea why it happens and how I can fix this ?

Deserializing a Compound document

Hi

I tried deserializing a compound json api document with the gem and found out this isn't supported as of now. For example, if the payload looks like this

{
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON API paints my bikeshed!"
    },
    "links": {
      "self": "http://example.com/articles/1"
    },
    "relationships": {
      "author": {
        "links": {
          "self": "http://example.com/articles/1/relationships/author",
          "related": "http://example.com/articles/1/author"
        },
        "data": { "type": "people", "id": "9" }
      },
      "comments": {
        "links": {
          "self": "http://example.com/articles/1/relationships/comments",
          "related": "http://example.com/articles/1/comments"
        },
        "data": [
          { "type": "comments", "id": "5" },
          { "type": "comments", "id": "12" }
        ]
      }
    }
  }],
  "included": [{
    "type": "people",
    "id": "9",
    "attributes": {
      "first-name": "Dan",
      "last-name": "Gebhardt",
      "twitter": "dgeb"
    },
    "links": {
      "self": "http://example.com/people/9"
    }
  }, {
    "type": "comments",
    "id": "5",
    "attributes": {
      "body": "First!"
    },
    "relationships": {
      "author": {
        "data": { "type": "people", "id": "2" }
      }
    },
    "links": {
      "self": "http://example.com/comments/5"
    }
  }, {
    "type": "comments",
    "id": "12",
    "attributes": {
      "body": "I like XML better"
    },
    "relationships": {
      "author": {
        "data": { "type": "people", "id": "9" }
      }
    },
    "links": {
      "self": "http://example.com/comments/12"
    }
  }]
}

One would have to manually to iterate over the data key and feed each resource into the Article deserializer.

class DeserializableArticle < JSONAPI::Deserializable::Resource
   has_one :author
    has_many :comments do | link, ids, types | do
       ....
    end
end

doc = JSON.parse(document)
doc["data"].map do |resource|
  DeserializableArticle.call(resource)
end

But going this way would mean other top level document related resources(the included key) wouldn't be available in the has_many block defined in the deserializer.
Is there a way to get the related resources added in the included top-level part of the document into the has_many/has_one block so we can easily get all the needed data deserialized together?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.