15

We are currently doing a mass upgrade from AngularJS to Angular. We've encountered a problem that i cannot find what is the best solution in order to solve it .

According to Angular/Typescript code standards, we should define all our variables, property names, and interfaces using camelCase.

The problem is that all the data that comes from the backend is used with snake_case.

So after each request, in order to create the according interface, we need to transform the keys to camelCase and then when we pass the data we need to snake_case it back.

we are using lodash to do so, but is there a better way doing so? Is there a way to convert those things using Typescript native implementation?

5
  • 4
    just define your interfaces as they come from the server. Commented Jun 8, 2017 at 14:05
  • Do you have any control of the serializer being used on the backend? Maybe it can be configured (I do this when using .NET Web API, to control how C# objects get serialized into JSON). Commented Jun 8, 2017 at 14:23
  • Did you ever figure out how to do this?? I'm currently in the same predicament. I have a response that is in snake_case but I need to work it in angular using camelCase. I tried adding an interface but it did nothing. Commented May 21, 2018 at 12:14
  • Unfortunately not. We ended rewriting our api to camel case Commented May 21, 2018 at 17:46
  • did anyone figure out a way to get this done? Commented Dec 12, 2019 at 14:43

2 Answers 2

4

The problem is the same as mine.

But I create common utils and resolve below,

Step 1: Create a function toCamel & keysToCamel

toCamel(s: string) {
    return s.replace(/([-_][a-z])/ig, ($1) => {
        return $1.toUpperCase()
            .replace('-', '')
            .replace('_', '');
    });
}

keysToCamel(o: any) {
    if (o === Object(o) && !Array.isArray(o) && typeof o !== 'function') {
        const n = {};
        Object.keys(o)
            .forEach((k) => {
                n[this.toCamel(k)] = this.keysToCamel(o[k]);
            });
        return n;
    } else if (Array.isArray(o)) {
        return o.map((i) => {
            return this.keysToCamel(i);
        });
    }
    return o;
}

Step 2: When JSON Data response from Backend.

Example:

JSON (response from backend)

{"user_id":"2014","full_name":"bamossza","token":"jwt","lang_id":"TH"}

Interface

export interface Profile {
    userId: number;
    fullName: string;
    token: string;
    langId: string;
}

convert and mapping to interface

this.profileService.callProfile(s.token)
    .subscribe((response: Profile) => {
        const profile = this.commonUtil.keysToCamel(response) as Profile;
        console.log(profile.fullName); // bamossza
        console.log(profile.langId); // TH
        ...
    });

Work for me.

Q: Why you do not convert until backend ???

A: Because I feel that JSON "calmelCase" is harder to read than "snake_case".

Try to apply the application to your project.

Sign up to request clarification or add additional context in comments.

2 Comments

For new versions of typescript: keysToCamel(o: any): any { if (o === Object(o) && !Array.isArray(o) && typeof o !== 'function') { const n: {[key: string]: any} = {}; Object.keys(o).forEach((k) => { n[this.toCamel(k)] = this.keysToCamel(o[k]); }); return n; } else if (Array.isArray(o)) { return o.map((i) => { return this.keysToCamel(i); }); } return o; }
why dont we just use some @Annotation that automatically transforms from camelCase to snake_case?
-2

Not sure if this helps. I did some experimentation that emulated the naming conventions for fields in the legacy database I am working with and found the following (demonstrated by example):

Model in C#...

public class WeatherForecast
        {
            public string DATE_FORMATTED { get; set; }
            public int TEMPERATURE_C { get; set; }
            public string SUMMARY { get; set; }

            public int TEMPERATURE_F
            {
                get
                {
                    return 32 + (int)(this.TEMPERATURE_C / 0.5556);
                }
            }
        }

...Maps to Interface in Typescript:

 interface WeatherForecast {
        datE_FORMATTED: string;
        temperaturE_C: number;
        temperaturE_F: number;
        summary: string;
    }

When I use this crazy looking convention, I get data just fine.

NOTE: have not tested PATCH/POST yet, but thought this might be helpful.

1 Comment

/r/lostredditors edit: this is SO, not Reddit. The Irony.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.