15

I'm currently working on a big JavaScript project and I'm struggling with mapping incomming JSON data (from the backend) to my own JavaScript objects.

I am using the Knockout JavaScript MVVM framework and although it includes a mapping plugin, it does not allow me to actually remap properties. I want to achieve this because the incomming JSON data is too fine grained, and I would like to 'flatten' my JS objects. An example follows.

Incomming data.

Object : {
    Description: {
        Id : 1,
        Title : 'ProductX'
    },
    Price : {
        Last : 12,
        Currency : 3
    }
}

And I would like to remap/flatten this to:

var mappedObject = {
    id : 1,
    title: 'ProductX',
    price : 12,
    currency : 3
}

Hence I would like to provide a mapping configuration, detailing what incomming properties should be mapped to what outgoing ones. Much like Dozer is being configured.

My question is: are there any libraries out there capable of what I'd like to achieve, or will this require me to build my own library?

thomaux
  • 19,133
  • 10
  • 76
  • 103

4 Answers4

10

It has been a while since this topic was last updated. Since people are probably still searching for object-to-object mappers nowadays:

Last year, I have created a port of the C# AutoMapper implementation to TypeScript / JavaScript exactly for this scenario. I have put the code at GitHub (https://b.ldmn.nl/AutoMapperTS). You can also use the library directly using the automapper-ts NPM or Bower package.

The library is almost fully documented. Furthermore, quite a lot of Jasmine unit tests are already available (code coverage is about 95%). They should provide you with some explanation of what you need.

I hope this library suits your needs. Should you have any questions and/or remarks, please don't hesitate contacting me!

DotBert
  • 1,262
  • 2
  • 16
  • 29
8

Well, I don't think there is any library for this as this sounds quite easy to do.

Here is an example:

var obj = {
    Description: {
        Id : 1,
        Title : 'ProductX'
    },
    Price : {
        Last : 12,
        Currency : 3
    }
},
    mappedObject = {};

function mapThat( obj, mappedObject ) {
    Object.keys( obj ).forEach( function( key ) {
        if ( typeof obj[ key ] === 'object' ) {
            // If it's an object, let's go recursive
            mapThat( obj[ key ], mappedObject );
        }
        else {
            // If it's not, add a key/value
            mappedObject[ key.toLowerCase() ] = obj[ key ];
        }
    } );
}

mapThat( obj, mappedObject );

console.log( mappedObject );​

Demo here: http://jsfiddle.net/qG6hm/

Florian Margaine
  • 58,730
  • 15
  • 91
  • 116
  • Thanks! I could be cleaner though. Calling the recursive function by repassing the argument looks ugly. No time to see how it could be better right now though. – Florian Margaine May 21 '12 at 13:40
  • 2
    This is more of a copier than a mapper which you could achieve with the spread operator or `Object.assign`. A mapper will let you map a property on the source obj to any property on the destination obj. In addition, it will let you add rules and resolvers for the mapper (ex: mapping numeric `14` to string `"14"`). – Kevin Aung Mar 15 '22 at 21:13
3

Actually, the knockoutjs mapping plugin allows you to do just that:

In the ko.mapping.fromJS call you can provide a mapping object that will be used to map the containing properties...

var mapper = {
    create: function(options){
        return { name: ko.observable(options.data.name) };
    }
};

This means that using this mapper with the mapping plugin, every object will be flattened to an object containing only it's name as an observable.

You use it like this:

var viewModel = ko.mapping.fromJS({id: 1, name: "a", desc: "b"}, mapper);

In this case, viewModel will only have a property name.

You can read more about this feature in the official documentation here.

Samir Hafez
  • 214
  • 1
  • 7
2
  1. you can use Object-mapper , this is very basic and simple library for object mapping in Javascript/JSON. when using this library, you need to specify the mapping property combinations and source and target types in a separate file.

  1. Also there is another library AutoMapper, this is slightly advanced. It can take care of mappings automatically based on property names, But you can still mention custom mapping for which ever it's not straight forward. If you're from .net background, this library implements in the same way as C# automapper.
IKriKan
  • 1,069
  • 12
  • 12
  • 5
    3. Also I created [Morphism](https://github.com/nobrainr/morphism) which benefits the support of TypeScript. This could help when you start having complex mappings or nested ones. Hope it could help someone looking to tackle this kind of tasks – Yann RENAUDIN Mar 21 '19 at 00:05