SyntaxError: Unexpected number in JSON at position 182 [duplicate] - node.js

I'm importing some JSON files into my Parse.com project, and I keep getting the error "invalid key:value pair".
It states that there is an unexpected "8".
Here's an example of my JSON:
}
"Manufacturer":"Manufacturer",
"Model":"THIS IS A STRING",
"Description":"",
"ItemNumber":"Number12345",
"UPC":083456789012,
"Cost":"$0.00",
"DealerPrice":" $0.00 ",
"MSRP":" $0.00 ",
}
If I update the JSON by either removing the 0 from "UPC":083456789012, or converting it to "UPC":"083456789012", it becomes valid.
Can JSON really not accept an integer that begins with 0, or is there a way around the problem?

A leading 0 indicates an octal number in JavaScript. An octal number cannot contain an 8; therefore, that number is invalid.
Moreover, JSON doesn't (officially) support octal numbers, so formally the JSON is invalid, even if the number would not contain an 8. Some parsers do support it though, which may lead to some confusion. Other parsers will recognize it as an invalid sequence and will throw an error, although the exact explanation they give may differ.
Solution: If you have a number, don't ever store it with leading zeroes. If you have a value that needs to have a leading zero, don't treat it as a number, but as a string. Store it with quotes around it.
In this case, you've got a UPC which needs to be 12 digits long and may contain leading zeroes. I think the best way to store it is as a string.
It is debatable, though. If you treat it as a barcode, seeing the leading 0 as an integral part of it, then string makes sense. Other types of barcodes can even contain alphabetic characters.
On the other hand. A UPC is a number, and the fact that it's left-padded with zeroes to 12 digits could be seen as a display property. Actually, if you left-pad it to 13 digits by adding an extra 0, you've got an EAN code, because EAN is a superset of UPC.
If you have a monetary amount, you might display it as € 7.30, while you store it as 7.3, so it could also make sense to store a product code as a number.
But that decision is up to you. I can only advice you to use a string, which is my personal preference for these codes, and if you choose a number, then you'll have to remove the 0 to make it work.

One of the more confusing parts of JavaScript is that if a number starts with a 0 that isn't immediately followed by a ., it represents an octal, not a decimal.
JSON borrows from JavaScript syntax but avoids confusing features, so simply bans numbers with leading zeros (unless then are followed by a .) outright.
Even if this wasn't the case, there would be no reason to expect the 0 to still be in the number when it was parsed since 02 and 2 are just difference representations of the same number (if you force decimal).
If the leading zero is important to your data, then you probably have a string and not a number.
"UPC":"083456789012"
A product code is an identifier, not something you do maths with. It should be a string.

Formally, it is because JSON uses DecimalIntegerLiteral in its JSONNumber production:
JSONNumber ::
-_opt DecimalIntegerLiteral JSONFraction_opt ExponentPart_opt
And DecimalIntegerLiteral may only start with 0 if it is 0:
DecimalIntegerLiteral ::
0
NonZeroDigit DecimalDigits_opt
The rationale behind is is probably:
In the JSON Grammar - to reuse constructs from the main ECMAScript grammar.
In the main ECMAScript grammar - to make it easier to distinguish DecimalIntegerLiteral from HexIntegerLiteral and OctalIntegerLiteral. OctalIntegerLiteral in the first place.
See this productions:
HexIntegerLiteral ::
0x HexDigit
0X HexDigit
HexIntegerLiteral HexDigit
...
OctalIntegerLiteral ::
0 OctalDigit
OctalIntegerLiteral OctalDigit

The UPC should be in string format. For the future you may also get other type of UPC such as GS128 or string based product identification codes. Set your DB column to be string.

If an integer start with 0 in JavaScript it is considered to be the Octal (base 8) value of the integer instead of the decimal (base 10) value. For example:
var a = 065; //Octal Value
var b = 53; //Decimal Value
a == b; //true

I think the easiest way to send your number by JSON is send your number as string.

Related

How to keep arbitrary number of trailing 0s in float?

I need to keep track of the number of significant digits in a number (float or integer). Trailing zeroes after a decimal point are considered significant, e.g. in 12.0 there are 3 significant figures and in 12.00 there are 4. I thought to use something like len(str(number)) but this removes all but one of the trailing zeroes from floats. The format() function and str.format() method, often suggested for similar questions (in integer, in float, and float again) would both seemingly require me to know in advance how many decimal points I wanted. Is there a good way to go about this? Should I just require the number to be inputted as a string so that all trailing zeroes are preserved? The code I'm using to find significant figures is below. I believe that it works for all cases except that described above.
def __init__(self, value):
"""Initializes a Sigfig object with the given value and finds the number of significant figures in value"""
assert type(value)==int or type(value)==float or type(value)==Sigfig, "Sigfig value must be of type int, float, or Sigfig"
# I wanted to avoid values of type str so that I don't have to worry about inputs like Sigfig('55b')
self.value=value #This is to allow math with full value to avoid losing precision to rounding
self.valuestring=f'{value}'
#Remove leading zeroes before or after a decimal point and scientific notation
self.remlead0enot=self.valuestring.lstrip('0').lstrip('.').lstrip('0').split('e',1)[0]
#Account for ambiguous zeroes before implied decimal point e.g. 1000
if '.' not in self.valuestring and self.valuestring[-1]=='0':
self.sigfigs=len(self.remlead0enot.rstrip('0'))
#Account for floats e.g. 1.005 and ints e.g. 105
else:
self.sigfigs=len(self.remlead0enot)-1 if '.' in self.remlead0enot else len(self.remlead0enot)
I'm not sure what you want to achieve but if if your question is if you can make a float remember with how many trailing zeros it was stored with: No.
You can only define how many points after the comma should be included when you convert the float to a string. But the float itself has no concept about significant digits. (Aka: 3.000000f == 3.0f)
If you need to know the amount of trailing zeros, yes, you need the input to be a string.
When you already have a string though you can also just store how many numbers are after the ..
arg_as_str = "3.100"
decimal_points = len(arg.split(".")[1]) # 3
as_float = float(arg) # 3.1
...
output_as_str = f"{as_float:{decimal_points}f}" # "3.100"
Hope that was helpful.
You can look into the package mpmath. This package is made specifically for this purpose, to allow arbitrary precision of floats.
https://mpmath.org/

Legal Statute Sorting Algorithm (Algorithmic Challenge)

I have designed a down and dirty sorting algorithm for New Jersey Legal Statutes, but I'm looking for a better way. Statutes are formatted in the following manner:
Title - A number < 999 and may include up to 2 letters after the title. Ex. 26, 26A, 26AA
Chapter - Formatted exactly the same as title.
Paragraph - A number < 999 which may be followed by 1-2 letters, and or a decimal point, and or a number < 999, and or a letter, and or another number. Ex. 25, 25.26, 25a, 25a.26, 25a.26b, 25aa.26, etc.
I convert the title and paragraph to decimals by stripping out the whole number in the beginning and dividing by 1000, giving me a decimal value which is converted to a string. I have assigned all letters(converted to lowercase) string values from 01-26. I add those values to the end of the initial whole number string sequentially. Any numbers also mixed in are added as their string value.
The obvious bottleneck is the mess of possibilities in the paragraph section. I have actually split that up to paragraph (pre any decimal) and section. I apply the above logic to the broken down sections if they exist.
As for the sorting 17 < 17A < 17AA < 17B < 18.
An example value conversion of 17B:26bb-2a5.1a5 would break down as the following:
Title- .01702
Chapter- .0260202
Paragraph- .002015
Section- .001015
Some more examples of statutes:
17:2-3
18B:2a-1
19AA:3-56g
26:56a-16
1:56-12.123
2:34–15.12a
The method I've devised is pretty dirty. I had to split it up in sections to ensure I had the correct values for each 'section' converting the whole number part to a decimal. I'm also using JS(Node) which doesn't handle large numbers well.
If anyone has a more efficient/clean way, any thoughts, or feedback, I'd greatly appreciate it.

Hash function to see if one string is scrambled form/permutation of another?

I want to check if string A is just a reordered version of string B. For example, "abc" = "bca" = "cab"...
There are other solutions here: https://www.geeksforgeeks.org/check-if-two-strings-are-permutation-of-each-other/
However, I was thinking a hash function would be an easy way of doing this, but the typical hash function takes order into consideration. Are there any hash functions that do not care about character order?
Are there any hash functions that do not care about character order?
I don't know of real-world hash functions that have this property, no. Because this is not a problem they are designed to solve.
However, in this specific case, you can make your own "hash" function (a very very bad one) that will indeed ignore order: just sum ASCII codes of characters. This works due to the commutative property of addition (a + b == b + a)
def isAnagram(self,a,b):
sum_a = 0
sum_b = 0
for c in a:
sum_a += ord(c)
for c in b:
sum_b += ord(c)
return sum_a == sum_b
To reiterate, this is absolutely a hack, that only happens to work because input strings are limited in content in the judge system (only have lowercase ASCII characters and do not contain spaces). It will not work (reliably) on arbitrary strings.
For a fast check you could use a kind af hash-funkction
Candidates are:
xor all characters of a String
add all characters of a String
multiply all characters of a String (be careful might lead to overflow for large Strings)
If the hash-value is equal, it could still be a collision of two not 'equal' strings. So you still need to make a dedicated compare. (e.g. sort the characters of each string before comparing them).

Hyphen with strings in PROC FORMAT

I am working with IC9 codes and am creating somewhat of a mapping between codes and an integer:
proc format library = &formatlib;
invalue category other = 0
'410'-'410.99', '425.4'-'425.99' = 1
I have searched and searched, but haven't been able to find an explanation of how that range actually works when it comes to formatting.
Take the first range, for example. I assume SAS interprets '410'-'410.99' as "take every value between the inclusive range [410, 410.99] and convert it to a 1. Please correct me if I'm wrong in that assumption. Does SAS treat these seeming strings as floating-point decimals, then? I think that must be the case if these are to be numerical ranges for formatting all codes within the range.
I'm coming to SAS from the worlds of R and Python, and thus the way quote characters are used in SAS sometimes is unclear (like when using %let foo = bar... not quotes are used).
When SAS compares string values with normal comparison operators, what it does is compare the byte representation of each character in the string, one at a time, until it reaches a difference.
So what you're going to see here is when a string is input, it will be compared to the 'start' string and, if greater than start, then compared to the 'end' string, and if less than end, evaluated to a 1; if it's not for each pair listed, then evaluated to a zero.
Importantly, this means that some nonsensical results could occur - see the last row of the following test, for example.
proc format;
invalue category other = 0
'410'-'410.99', '425.4'-'425.99' = 1
;
quit;
data test;
input #1 testval $6.;
category=input(testval,category.);
datalines;
425.23
425.45
425.40
410#
410.00
410.AA
410.7A
;;;;
run;
410.7A is compared to 410 and found greater, as '4'='4', '1'='1', '0'='0', '.' > ' ', so greater . Then 410.7A is compared to 410.99 and found less, as '4'='4', '1'='1', '0'='0', '7' < '9', so less. The A is irrelevant to the comparison. But on the row above it you see it's not in the sequence, since A is ASCII 41x and that is not less than '9' (ASCII 39x).
Note that all SAS strings are filled to their full length by spaces. This can be important in string comparisons, because space is the lowest-valued printable character (if you consider space printable). Thus any character you're likely to compare to space will be higher - so for example the fourth row (410#) is a 1 because # is between and . in the ASCII table! But change that to / and it fails. Similarly, change it to byte(13) (through code) and it fails - because it is then less than space (so 410^M, with ^M representing byte(13), is less than start (410)). In informats and formats, SAS will treat the format/informat start/end as being whatever the length that it needs to - so if you're reading a 6 long string, it will treat it as length 6 and fill the rest with spaces.

TryStrToFloat converts incorrect string

I'm using TryStrToFloat to convert string to Double variables. Everything works fine until string doesn't looks like '21e'. I get result of conversion 21.
It seems to me that compiler treats '21e' like number 21e0. String 21e1 gives result 210.
When I use Val function conversion works better. String '21e' gives error, but now '21e1' gives 210, '21e-1' gives number 2,1 etc.
How to make correct working of conversion. Should I detect letter 'e' in text, or is any simply way to convert ?
The documentation says:
Use TryStrToFloat to convert a string, S, to a floating-point value. S must consist of an optional sign (+ or -), a string of digits with an optional decimal point, and an optional mantissa. The mantissa consists of 'E' or 'e' followed by an optional sign (+ or -) and a whole number. Leading and trailing blanks are ignored.
Your input does not satisfy the conditions and so should be treated as an error.
You did not say so explicitly, but I presume that you claim that:
TryStrToFloat('21e', val)
returns True. If so, this is a bug and should be reported to Embarcadero. If you need to work around this then I suggest you code your own function that detects this case and handles it correctly.
On the other hand, if that function call returns False the function is behaving as designed and your mistake is to read the value in val.
Update
I can confirm that TryStrToFloat('21e', val) returns True. I tested on XE7 update 1. I submitted the following bug report to Embarcadero: https://quality.embarcadero.com/browse/RSP-9814

Resources