2

I have been working on my own small API, so far everything works super fine, i just have a small cosmetic issue I can#t seem to find an answer to.

I defined a schema like so in mongoose:

const ArtistSchema = new Schema({
stageName: {
    type: String,
    unique: true,
    required: true,
    minlength: 3,
    maxlength: 255
},
realName: {
    type: String,
    unique: true,
    required: true,
    minlength: 5,
    maxlength: 255
},
birthday: {
    type: Date,
    required: true
},
debutDate: {
    type: Date,
    required: true
},
company: {
    type: String,
    minlength: 5,
    maxlength: 255,
    required: function () {
        return this.active;
    }
},
active: {
    type: Boolean,
    default: true
},
music: [AlbumSchema],
createdAt: {
    type: Date,
    default: Date.now
}
});

I can create an entry in the database, with no problem either. I use this function on app.post

    create(req, res, next) {
    const artistProps = req.body;
        Artist.create(artistProps)
            .then(artist => res.send(artist))
            .catch(next);
   },

This works good, but the res.send(artist)) actually returns the object with no key order.. or in a pattern I cannot recognize. I want the response to be the same sorting as i defined in the schema, beause now it returns it:

active, stagename, realname, label, music, birthday

while it should be stagename, realname, birthday, debutDate etc..

I hope someone can help me out here. I know i can sort the VALUEs of a specific key with sort (like sort stageName alphabetically) but I really cant find anything for the keys .

1 Answers1

1

Express' res.send method recognizes that artist is an Object, and calls JSON.stringify on it to convert the Object to a JSON string before sending. Simplifying a bit, the JSON.stringify method iterates through your artist object keys in the order they were created. (Here's a link to the more complicated ordering explanation.) That explains the current behavior.

Others may chime in with their own proposals for how you might do what you're aiming for, but here's a simple one to try first:

  • First, do your own JSON.stringify, using a "replacer" to create the output order that you want:

    const artistString = JSON.stringify(artist, ["realName", "stageName", ...])
    // '{"realName": "Paul David Hewson", "stageName": "Bono", ...}'
    
  • Then, use res.json(artistString), rather than res.send, to send your JSON string with the correct Content-Type header. (res.send will assume you want Content-Type: “text/html”.)

There are definitely more complicated approaches, including creating a function that gets keys, sorts them, and returns a replacer; or writing your own .toJSON() substitute for JSON.stringify. You may need to implement one of these approaches, because you have nested objects; the behavior of the replacer can be a bit wonky in this case. You might be able to list the nested properties immediately after the parent, like:

["realName", "type", ...]

but since you have the same names for some nested properties, this may or may not work for you. You might have to stringify the insides before you stringify the outsides (gah!).

In any case, hopefully my suggestion can be a first step.

Andy Taton
  • 441
  • 4
  • 8