Code Monkey home page Code Monkey logo

Comments (8)

danivek avatar danivek commented on August 17, 2024

Hi @sartian,

Actually serialize functions only support serialization of one type at time, and there is no way to serialize multiple types at once.

We could had a function with an option that will look at a reference path in data to determine which type to use to serialize.
Each object should have the same reference path to determine the type to use.

 [{
    type: 'articles',
    title: 'First article'
 },
 {
    type: 'books',
    title: 'First books'
 }
 // ...
 ]

Then (proposal) :

Serializer.serialize({
  refPath: 'type', // the reference path to look to determine which type to use to serialize
  topLevelMeta: function(extraOptions) {
    return {
      count: extraOptions.count,
      total: extraOptions.total
    }
  },
  topLevelLinks: {}
}, data, extraOptions)

@Mattii any thoughts ?

from json-api-serializer.

sartian avatar sartian commented on August 17, 2024

That sounds like an approach that could work, I am guessing the parameter is named 'refPath' instead of 'type' due to links creation? Hrm. To make it elegant from a data perspective maybe there could be a type and typePathMappings (?got a better name?). With type mappings the type could be specified on the entry itself and the map would indicate resource path to use. (I'm new to this api, apologies of it already has support for that in some capacity). Like mappings of {'book': 'books', 'article': 'articles', 'review': 'reviews'}. If we had an data back-end that kept references of books and articles affiliated with certain authors and we exposed it for searching it like so:

http://localhost:3000/search?q=neil+gaiman&page[offset]=0&page[limit]=3

...the raw unserialized hits returned from a back-end datastore might look like this:

[{
    "id": 14,
    "type": "article",   
    "authors": [ "Neil Gaiman"],
    "title": "Neil Gaiman: ‘Terry Pratchett isn’t jolly. He’s angry’",
    "url": "https://www.theguardian.com/books/2014/sep/24/terry-pratchett-angry-not-jolly-neil-gaiman"
},
{
    "id": 37,
    "type": "review",
    "book": "Good Omens",
    "authors": [ "Neil Gaiman", "Terry Pratchett" ],
    "title": "Good Omens: The Nice and Accurate Prophecies of Agnes Nutter, Witch",
    "url": "http://www.goodreads.com/book/show/12067.Good_Omens"
},
{
    "id": 15,
    "type": "book",
    "book": "American Gods",
    "authors": [ "Neil Gaiman" ],
    "title": "Neil Gaiman | Neil's Work | Books | American Gods",
    "url": "http://www.neilgaiman.com/works/Books/American+Gods/"
}]

...whereas the top-level JSON:API serialized response should look something like this:

{
  "meta": {
    "hits": 3,
    "total-hits": 7,
    "page": { "offset": 0, "limit": 3 }
  },
  "data": [
    {
      "id": 14,
      "type": "article",
      "attributes": {
        "authors": [
          "Neil Gaiman"
        ],
        "title": "Neil Gaiman: ‘Terry Pratchett isn’t jolly. He’s angry’",
        "url": "https://www.theguardian.com/books/2014/sep/24/terry-pratchett-angry-not-jolly-neil-gaiman"
      },
      "links": { "self": "/articles/14" }
    },
    {
      "id": 37,
      "type": "review",
      "attributes": {
        "book": "Good Omens",
        "authors": [
          "Neil Gaiman",
          "Terry Pratchett"
        ],
        "title": "Good Omens: The Nice and Accurate Prophecies of Agnes Nutter, Witch",
        "url": "http://www.goodreads.com/book/show/12067.Good_Omens"
      },
      "links": { "self": "/reviews/37" }
    },
    {
      "id": 15,
      "type": "book",
      "attributes": {
        "book": "American Gods",
        "authors": [
          "Neil Gaiman"
        ],
        "title": "Neil Gaiman | Neil's Work | Books | American Gods",
        "url": "http://www.neilgaiman.com/works/Books/American+Gods/"
      },
      "links": { "self": "/books/15" }
    }
  ],
  "links": {
    "self": "/search?q=neil+gaiman&page[offset]=0&page[limit]=3",
    "first": "/search?q=neil+gaiman&page[offset]=0&page[limit]=3",
    "prev": null,
    "next": "/search?q=neil+gaiman&page[offset]=3&page[limit]=3",
    "last": "/search?q=neil+gaiman&page[offset]=6&page[limit]=3"
  }
}

Given this example use case, I'm not sure what is the best approach, maybe a registry of type mapping to resource serializers? From a data design standpoint, when I annotate an object in the system with a type, we want to use the singular form, but for mapping to a resource endpoint that return collections, it makes sense that resource/reference paths use plural version. Thanks!

from json-api-serializer.

danivek avatar danivek commented on August 17, 2024

'refPath' has nothing to do with links creation. Maybe I have not choose the right name for this parameter. In my first intention if you have register type like this :

Serializer.register('article', options);
Serializer.register('book', options);
Serializer.register('review', options);

And if your data might look like this :

const data = [{
    "id": 14,
    "type": {
      "kind": "article"
    },
    "authors": ["Neil Gaiman"]
  },
  {
    "id": 37,
    "type": {
      "kind": "review"
    },
    "book": "Good Omens",
  },
  {
    "id": 15,
    "type": {
      "kind": "book"
    },
    "book": "American Gods",
  }]

We could have an option refPath or pathForType or whatever, which is the path to look in data to determine dynamically which type to use to serialize. (of course type should be register before)

Like so :

Serializer.serialize({
  pathForType: 'type.kind' // or refPath or whatever
}, data)

Maybe you got a better name ?

from json-api-serializer.

sartian avatar sartian commented on August 17, 2024

Hi @danivek,

Your suggestion with parameter sounds like a clean way to handle it.

My question about variable naming convention for 'refPath' vs the id variable being called "id" (located here I think: https://github.com/danivek/json-api-serializer/blob/master/lib/JSONAPISerializer.js#L38) and I was just curious why it wouldn't use the name "key". I see this line in optionsSchema:

id: joi.string().default('id'),

...and was curious why (from a design perspective) the next line wouldn't look something like this:

key: joi.string().default(null),

...in this example, it defaults to null as a way to preserve backwards compatibility so it continues to ignore type if included in the data, but if specified the path to the type indicator is adhered to.

I didn't know if there was a particular reason that pathForType wasn't called key like the path for id is called id. In any case, pathForType is a very clear to understand parameter name, thanks! - @sartian

from json-api-serializer.

danivek avatar danivek commented on August 17, 2024

How could it work if we had this kind of option in options of a resource's type. In other words, what's happen if each type's options define a different "path" ?

How do we call serialize function ? without first parameter ?

from json-api-serializer.

mattiloh avatar mattiloh commented on August 17, 2024

Interesting use-case, @sartian! I think @danivek's proposal of a object as first parameter is good, but maybe we could make it more flexible by adding a function, which derives the type from each data-item?

Serializer.serialize(item => item.type, data)

Then we could say type of serialize(type, data) can be a string or a function deriving a type-string from each data-item. This function can be very sophisticated and determine different types of items.

If that's too cryptic to read, we could wrap it into an object and give it a name.

Serializer.serialize({ type: item => item.type }, data)

from json-api-serializer.

danivek avatar danivek commented on August 17, 2024

@Mattii Very interesting proposal. I think we also need to redefine 'topLevelMeta' and 'topLevelLink' options when serialize. The second solution with an object is the best way I think (much more customizable).

What about a second function to have an isolated API ?

Serializer.serializeMixed({ type: item => item.type }, data)

from json-api-serializer.

mattiloh avatar mattiloh commented on August 17, 2024

Yes, you're right! For this use-case topLevelMeta and topLevelLink can't be defined during registrations of a schema. They need to be defined during serialization.

Putting it into a separate function is fine for me, but we need to take care about keeping the code DRY. The async-serialization already duplicated some logic of the default-serialization. We should definitely open an issue to improve that. But maybe it would be interesting to implement serializeMixed before, to know all requirements for the shared logic. What about asynchronicity? I would favour it, as everything blocking has the potential to bring up performance issues very soon.

from json-api-serializer.

Related Issues (20)

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.