The main stuff
I receive an MQTT packet (which appears as an ASCII array to the buffer in format [after being printed using stringify]):
packet = {
"cmd": "publish",
"retain": true,
"qos": 1,
"dup": false,
"length": 36,
"topic": "topic/subtopic",
"payload": {
"type": "Buffer",
"data": [123,34,50,57,34,58,43,52,52,55,56,53,49,54,56,53,50,51,52,125]
},
"messageId": 3
}
packet.payload converts to {"29":+447...} which is the beginning of a mobile number. When passed into JSON.parse(packet.payload), it throws SyntaxError: Unexpected token + in JSON at position 6.
My question is how can I extract the value (and less importantly, the key)?
Extra (probably unnecessary) context you can skip over
The error makes sense since + isn't a valid number type and it's not encased as a string.
I attempted convert the value to a string using a reviver function and a filter, with no success, nor was I able to get the whole thing treated as a string with JSON.stringify(packet.payload), packet.payload.toString() or String(packet.payload). I can do a manual conversion from ASCII chars to string between {, : and } but I'm looking for a more robust, generalised solution that doesn't manipulate the ASCII.
Parsing works as expected on a different packet {"6000":100} to give an expected key value pair return.
Using .entries() returned some weird behaviour - (on the other packet) it returned 6000,100 which was of array type, but unusable as an array or number (as far as I could figure out). This might hint as to what's going on?
I was also wondering whether it was possible to extend the behaviour of .parse() to accept a number in the form +44... or to take that value and return it as "+44...".
Edit for extra clarity:
The first thing I wanted to do was limit the output datatypes from the upstream device (a PLC) to primitives (like int) only, however this isn't possible or even enforceable, so my broker needs to be able to handle whatever is thrown at it even if it's invalid type.
With regards to why the packet comes in a JSON format? I honestly don't know - but I'd think it's either how MQTT natively works, or the Aedes broker service I'm running on Node.
The broker has an event publish which will emit the client and the packet whenever a publisher publishes a packet. This is how I am receiving the packet on the server end of things.
The following code will take the array and convert it back to a string via a buffer.
var buffer = Buffer.from(packet.payload.array)
var string = buffer.toString('utf8')
In that case that packet.payload is already a buffer then the following should work:
var buffer = Bufffer.from(packet.payload)
EDIT:
var regex = /{ \"\d+\": (\+\d+) }/
var matches = packet.payload.toString('utf8').match(regex)
var phoneNumber = matches[1]
Related
the problem is:
I have a request with params like:
{ "foo": "bar", "bar": "baz", "baz" : { "nestedKey": "foo" } }
I need to sign it with Hmac512 algorithm, so I'll need to stringify the object first.
But, my concern is, if the order of the key isn't preserved, the signature generated by server and the client could be different.
to handle that, my idea is simply to order the keys of the object (including the keys nested inside that object).
how can I achieve this?
As stated in the OP, the input to the HMAC process must be deterministic.
But Javascript object elements' order cannot be set, no matter how much we'd like them to be settable. (I see this question re-occur every so often.)
Answer is to sort the the stringified string itself.
See json-stable-stringify for a solution.
Then feed the resulting string into the HMAC method. No need to base64 encode it.
You need to ensure that the message is the same in both sides, but you should not need to modify or adapt the message at all
Basically apply this algorithm
base64(sign(utf8(json message)))
Client side
Stringify: Convert the javascript object to string
UTF-8: Ensure you are using a known and fixed encoding like utf
Sign: Calculate HMAC over the resulting message
base64: Convert the binary signature to base64
Send to client the json message and the signature
Server side
Get the raw message from client and apply steps 2-4. Check if the signatures are equal
I've an ASP.NET MVC application, C#, and some numbers into my Model in decimal type, which treat the fractional part as comma (i.e. 12,5).
I serialize them and send to the client using JSON, which correctly convert the comma to point:
var result = Json(new { Value = myModel.myValue }); // become Value = 12.5
Than I process the data client side, with some math function, getting the number value always with point (i.e. 12.5 * 3 = 37.5).
But, when I need to post back to the server the processed value, if I keep the point and I store the value into my Model (which is decimal, as said), it truncate the values after the point.
Do I really need to do result.replace('.', ',') before sending back data client side? Damn not so good. Best practices?
The paradox is that for mvc's jquery validator (being decimal required) I need to print the value into the input box with comma. The round-trip is crazy...
You can use stringify - This converts a JavaScript object into a string,
var myJSON = JSON.stringify(Yourvalue);
This may be helpful, rather than burdening the server with the client's wild choice of encoding, get the javascript to do it.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString
It nicely turns 98.76 into 98,76 when passing it through 'it-IT'
I have a Java JSON Object, its format is [{a=b}], I am trying to pass this object into javascript as a JSON object but its missing " on both the key and value as well as having "=" instead of ":"
Is there a simple way of converting this JAVA JSON object to be consumable by different services?
Parsing is proving to be very complicated as the actual JSON is nested and the lack of quotations and the lacking of indications for nestedness.
Sample of 'JSON' data:
[{wwnType=Virtual, serialNumberType=Virtual, connections=[], modified=2016-10-29T19:00:04.457Z, macType=Virtual, category=server-profile-templates, serverHardwareTypeUri=/rest/server-hardware-types/32006464-D3C6-4B4E-8328-47A193C6116C, bios={overriddenSettings=[], manageBios=false}, firmware={firmwareBaselineUri=null, manageFirmware=false, forceInstallFirmware=false, firmwareInstallType=null}, boot={manageBoot=true, order=[CD, Floppy, USB, HardDisk, PXE]}, hideUnusedFlexNics=true, bootMode=null, state=null, affinity=Bay, localStorage={controllers=[]}, type=ServerProfileTemplateV1, status=OK, description=, eTag=1477767604457/1, serverProfileDescription=test, name=test, created=2016-10-29T19:00:04.428Z, enclosureGroupUri=/rest/enclosure-groups/e989621b-930e-40e7-9db0-a6ddbf841709, uri=/rest/server-profile-templates/db1dbdcc-4237-4452-acc3-cf9dfdc75365, sanStorage={manageSanStorage=false, volumeAttachments=[]}}]
Thanks
It's not going to be simple. However, I think you can do this without writing a full-fledged parser, as long as you're willing to write a tokenizer, or lexical analyzer, to break your input string into tokens. The basic plan could be something like:
Convert your input into a list of tokens. I don't know what the format of your input is, so you'll need to do your own analysis. A token would be something like a single character [, ], {, }, comma, =; or an identifier (a or b in your example, but I don't know what the possible valid formats are); or, maybe, a string literal in quotes, or a numeric literal, depending on what your needs are.
Go through the string and replace the tokens you need to. Based on your example, I'd say that after a {: if the first token after that is an identifier, put it in quotes; if the second token after that is =, change it to :; if the third token after that is an identifier, put it in quotes. The same could be true after a comma, but you'll need to keep track of whether the comma is a separator for a list of key-value pairs in an object, or a list of values in an array. For that, you may need to keep a stack that you push whenever you see [ or {, and pop whenever you see } or ], so that you know whether you're inside an object or an array.
After you're done replacing everything, concatenate the tokens back together. The result should be a well-formed JSON object.
This is just a rough outline, since I really don't know all your requirements. You'll probably have to adapt this answer to meet your exact needs. But I hope this helps as a general idea of how you could approach the problem.
Sorry, I don't think there's a simpler answer, except that you might want to look into parser generators (see Yacc equivalent for Java). I haven't actually looked at any in Java, so I don't know how simple they are to use. Please don't try to solve the whole thing with regexes. (Regexes will be useful for breaking your string into tokens, but trying to do more than that with regexes is likely to produce nothing but migraine.)
I think isn't json object. json object should be like this.
Example:
JSONObject obj = new JSONObject();
obj.put("a", "b");
obj.put("name", "your name");
Output: {"a": "b", "name":"your name"}
Passing into javascript
var obj = '{"a": "b", "name":"your name"}',
var json = JSON.parse(obj);
On sql server : Out put : 0x5C8C8AAFE7AE37EA4EBDF8BFA01F82B8
SELECT HASHBYTES('MD5', convert(varchar,getdate(),112)+'mytest#+')
On JavaScript : Out put : 5c8c8aafe7ae37ea4ebdf8bfa01f82b8
//to get Md5 Hash bytes
vm.getMd5Hashbytes = function () {
var currentDate = moment().format('YYYYMMDD');
var md5Hash = md5.createHash(currentDate + 'mytest#+');
return md5Hash;
}
angular-md5 module
Q : Can you tell me why this difference ? SQL server shows 0x as prefix.Why ?
This is purely a formatting issue. Both versions are producing an identical sequence of bytes. SQL Server and node just have different conventions when it comes to presenting these bytes in a human readable format.
You can get similar formatting by specifically telling SQL Server how to format your binary data
declare #hashAsBinary varbinary(max)
declare #hashAsText char(32)
set #hashAsBinary = HASHBYTES('MD5', '20160818mytest#+')
set #hashAsText = LOWER(CONVERT(varchar(max), #hashAsBinary, 2))
select #hashAsText
Which outputs:
5c8c8aafe7ae37ea4ebdf8bfa01f82b8
See SQL Server converting varbinary to string
I am not sure how else to explain it but it will take more space than a comment allows for so I will post it as an answer.
Look at the source code that you are referencing. At the end (lines 210 and 212) you will see it converts the binary value to a hex string (and then to lower case which does not matter unless you opt for a string comparison at the end). End result = your JavaScript library returns a representation using the type string formatted as hex.
Your Sql function HASHBYTES on the other hand produces a varbinary typed result (which is a different type than string (varchar)).
So you have 2 different data types (each living on their own space as you have not pulled one to the other). You never mention where you are doing the comparison, ie: on the database or are you pulling from the database to script. Either way to do a comparison you need to convert one type so you are either comparing 2 strings types OR comparing two binary types. If you do not compare similar types you will get unexpected results or run time exceptions.
If you are comparing using strings AND in JavaScript then look at your library that you are referencing, it already has a call named wordToHex, copy and paste it and reuse it to convert your Sql result to a string and then do a string comparison (do not forget to compare case insensitive or also make it lower case).
Edit
WebApi is black box for me.It is a 3rd party service.I just need to send the security token as mentioned above.
Assuming that the type accepted by that web api is byt[] appending 0x to your string in javascript and then sending it to the web api should work as in the web api will then translate the incoming parameter as a byte array and execute the comparison using the correct types. As this is a black box there is no way to know for certain unless you either ask them if the accepted type is indeed a byte array or to test it.
I am trying to run a query with a filter on a string column, but at runtime a few filter values (e.g. 'PO Box 27') result in failed queries. When trying to filter using my query fails with the error message: "The string 'PO Box 27' is not a valid TimeSpan value."
Code:
var crmAccountsQuery = EntityQuery
.from('crmAccountEFs')
.where(breeze.Predicate.create('address1_Line1', 'eq', 'abc'));
return manager.executeQuery(crmAccountsQuery)
.then(function (data) {
crmAccountsObservable(data.results);
return;
})
.fail(queryFailed);
The breeze.js on the client builds a url like:
http://localhost:49800/breeze/BreezeDb/crmAccountEFs?$filter=(Address1_Line1%20eq%20time'PO%20Box%2027')
The time typing is completely wrong.
Edit:
related to: BreezeJS malformed OData query Url when using "startsWith"
For others benefit I found the unexpected answer. Turns out the case of the 'from' entityType was wrong (CrmAccountEFs), but no error is raised. The server handles case change, and the client silently falls back to an anonymous type (as the code is attempting to cope with Projection Queries). This is in EntityQuery._getFromEntityType().
The consequences are when the Query is run, the resource name is not resolved to an entityType. Instead it is given an anonymous entityType, which means the column's type has to be inferred from it's value. In my case a leading 'P' meant it is typed as Time. But when the resulting url is read by the server it fails trying to cast it to the correct type.
//var query = breeze.EntityQuery.from("Todos"); //Ok
//wrong case => entityType = Anonymous => column's type inferred from value
var query = breeze.EntityQuery.from("todos"); //Error
http://jsfiddle.net/rockresolve/C4A
Breeze Devs:
This subtle error is difficult to track down (and may be raised by other string type inferences).
Is it possible to have EntityQuery by default expect a resourceName which is a valid entityType, and only allow an Anonymous type when an explicit parameter is set.