简体   繁体   中英

What is @JsonProperty equivalent in Node.js (or JavaScript)?

I want to rename json objects' keys in Node.js(or JavaScript). Like how we use @JsonProperty to rename in java is there something equivalent in JavaScript to do the same?

I wrote the following code in java to change the keys' name(from caps to camel case) of a json object.

public class Rename {
    @JsonProperty("STUDENT_ID")
    private String studentId;
    @JsonProperty("STUDENT_NAME")
    private String studentName;

    public String getStudentId() {
        return studentId;
    }

    public void setStudentId(String studentId) {
        this.studentId = studentId;
    }

    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }

    @Override
    public String toString() {
        return "{" + 
                 "\"studentId\":\"" + studentId + '\"' +
                 ", \"studentName\":\"" + studentName + '\"' +
               '}';
    }

}

I want to do the same in Node.js. Is there any annotation or any methods available to do it?

This is what I have done till now:

class Rename {
    studentId = '';
    studentName = '';

    getStudentId = function() {
        return studentId;
    }

    setStudentId = function(studentId) {
        this.studentId = studentId;
    }

    getStudentName = function() {
        return studentName;
    }

    setStudentName = function(studentName) {
        this.studentName = studentName;
    }

    // I'm not sure how to write toString() function
}

const info = require('./file.json')
info.forEach(node => {
    let n = node;
    let obj = new Rename();
    // I am confused how to call toString()
}

file.json looks like:

[
  {
    "STUDENT_ID": "1",
    "STUDENT_NAME" "abc"
  },
  {
    "STUDENT_ID": "2",
    "STUDENT_NAME" "xyz"
  }
]

I want the output to be:

[
  {
    "studentId": "1",
    "studentName" "abc"
  },
  {
    "studentId": "2",
    "studentName" "xyz"
  }
]

There is no equivalent baked into JavaScript.

The @JsonProperty comes from the Jackson library , so it is not even part of Java. It is a convenience for the serialiser/deserialiser to rename a property.

A custom function can be defined that does renaming of properties:

 const renamer = (mappings, obj) => Object.fromEntries( Object.entries(obj).map(([key, value]) => [mappings.get(key)?? key, value]) ); const student = { studentId: "123", studentName: "Fred" }; const studentMappings = new Map().set("studentId", "STUDENT_ID").set("studentName", "STUDENT_NAME"); const renamed = renamer(studentMappings, student); console.log(renamed);

And with it a serialiser/deserialiser pair can be created for a data type:

 const renamer = (mappings, obj) => Object.fromEntries( Object.entries(obj).map(([key, value]) => [mappings.get(key)?? key, value]) ); const invertMap = map => new Map(Array.from(map, ([k, v]) => [v, k])); const dataHandler = mappings => ({ serialiser: obj => JSON.stringify(renamer(mappings, obj)), deserialiser: json => renamer(invertMap(mappings), JSON.parse(json)) }); const student = { studentId: "123", studentName: "Fred" }; const studentMappings = new Map().set("studentId", "STUDENT_ID").set("studentName", "STUDENT_NAME"); const studentDataHandler = dataHandler(studentMappings); const serialised = studentDataHandler.serialiser(student); console.log("serialised:", serialised); console.log("deserialised:", studentDataHandler.deserialiser(serialised));
 .as-console.wrapper { max-height: 100%;important; }

For only serialisation, this can be achieved closer to Jackson's behaviour by providing a custom Object#toJSON() method which will automatically be called when serialising with JSON.stringify() .

A generic function can be defined with the purpose to be re-used on many objects. This function can look up the mappings from the object instance using a known symbol and proceed with the renaming:

 const renamer = (mappings, obj) => Object.fromEntries( Object.entries(obj).map(([key, value]) => [mappings.get(key)?? key, value]) ); function implicitRename() { const mappings = this[Symbol.for("serialisationMappings")]?? new Map(); return renamer(mappings, this); } const studentMappings = new Map().set("studentId", "STUDENT_ID").set("studentName", "STUDENT_NAME"); const student = { studentId: "123", studentName: "Fred", [Symbol.for("serialisationMappings")]: studentMappings, toJSON: implicitRename }; class StudentClass { get [Symbol.for("serialisationMappings")]() { return studentMappings; } constructor(id, name) { this.studentId = id; this.studentName = name; } toJSON() { return implicitRename.call(this); } } const serialisedPlainObject = JSON.stringify(student); console.log("serialised plain object:", serialisedPlainObject); const studentInstance = new StudentClass("321", "Barney"); const serialisedClassInstance = JSON.stringify(studentInstance); console.log("serialised class instance object:", serialisedClassInstance);
 .as-console.wrapper { max-height: 100%;important; }

As can bee seen, this can work on classes and plain objects. However, it is one-way only: when serialising to JSON. The conversion from JSON to an object (when using JSON.parse() ) cannot be done generically because the JSON result does not provide information about the type nor which mappings to use.

Something similar to dataHandler implementation above can be used if a function is defined to deserialise each type.

For classes specifically, a static fromJSON() method can be provided which will know what the mappings are. However, the implementation would need to vary based on the object. For example, for the StudentClass it could look like this but other classes might need other ways to be instantiated (from a factory method or otherwise):

class StudentClass{
  /* ... */
  static fromJSON(json) {
    const obj = JSON.parse(json);
    
    return new StudentClass(obj.STUDENT_ID, obj.STUDENT_NAME);
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM