简体   繁体   中英

How to convert a buffer to string/number/date without knowing the original type

I am writing a query service that connects to a HBase and supports different GET/POST queries. The retrieved data is an array of objects where the key is the name of the column and the value is a buffer .

However, a simple columns[columnName].toString() for each column of an object doesn't work, since there are fields that can be string, date or numbers. .toString works okay for string/date, but the numbers are returned in a format like this: "all": "\\\\\\\\�", .

A brute force (I do realize it's not a pretty code I was testing things) approach was something like this:

function parseEntry(entry) {
    let parsed = {};
    Object.keys(entry.columns).forEach(column => {
        const value = entry.columns[column].value;
        parsed[column] = (typeof value === 'object' && value.length <= 8) ?
            value.readInt32BE(4) :
            value.toString();

    });

    return parsed;
}

But sometimes I get strings whose length is < 8 and I'll try to convert them to numbers, undesired behavior. I also tried to test the value with a regex like /[^\-\￿]+/.test(value) but for some reason the tests return false for every entry.

I tried every possible combination of .toString , JSON.parse , .trim , readInt32BE etc. but I did not succeed to properly parse an object like this. Is there a way to properly do it without a lot of if conditionals based on the name of the column?

Edit : An entry in my response array looks like this (if it helps you to test things; I stripped some fields for security purposes; all should be a number, cUS and fs should be dates, fqdn it's a string and val is an IP which is also a string).

{ 'd:all': 
      { value: <Buffer 00 00 00 00 00 00 04 8e>,
        timestamp: [Int64 value:1553606385109 octets:00 00 01 69 ba 28 1d d5] },
     'd:cUS': 
      { value: <Buffer 32 30 31 39 2d 30 33 2d 32 36 54 31 32 3a 35 36 3a 30 39 2e 31 37 37 5a>,
        timestamp: [Int64 value:1553604980146 octets:00 00 01 69 ba 12 ad b2] },
     'd:fqdn': 
      { value: <Buffer 61 70 69 2d 67 6c 6f 62 61 6c 2e 6e 65 74 66 6c 69 78 2e 63 6f 6d>,
        timestamp: [Int64 value:1553606699454 octets:00 00 01 69 ba 2c e9 be] },
     'd:fs': 
      { value: <Buffer 32 30 31 39 2d 30 33 2d 32 32 54 31 35 3a 30 30 3a 31 33 2e 35 30 32 5a>,
        timestamp: [Int64 value:9005645987910764 octets:00 1f fe 96 5a 15 14 6c] },
     'd:val': 
      { value: <Buffer 35 32 2e 32 30 39 2e 31 33 30 2e 31 37 32>,
        timestamp: [Int64 value:1553606699454 octets:00 00 01 69 ba 2c e9 be] },
}

You can convert your string to a number with the following. \ represents one character so you simply need to use . to match it. Then using String#charCodeAt you can transform it to a number.

The charCodeAt() method returns an integer between 0 and 65535 representing the UTF-16 code unit at the given index.

 const res = "\\\\\\\\�" .match(/./g) .map(v=>v.charCodeAt()); console.log(res);

But in general, you'll need conditions to check to see what method you should use to convert the buffer.

Which can be done with Buffer package, by passing the type (hex, binary, utf8 (default), or ascii) as a parameter.

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