LDAP has two numeric syntaxes and matching rules intended for very different use cases:
- Integer syntax for representing integers (duh!). The matching rule compares integers as you'd expect, larger numbers sort after smaller numbers. For example, 100 is greater than 20
- Numeric string syntax for representing strings of digits and white space. Typical use cases are credit card numbers, account numbers, social security numbers, etc. They are compared as regular strings. For example, 100 is less than 20.
It's worth noting that LDAP does not have a standard syntax or matching rules for arbitrary precision floating point numbers. Client applications typically multiply values by a factor in order to eliminate fractional parts. For example, a bank balance would be represented in cents, not dollars, by multiplying values by 100.
Our REST APIs use JSON which has a single numeric primitive type representing integers or arbitrary precision floating point numbers that may include an exponent.
We have observed client applications submitting integer values as floating point numbers with a zero fractional part, e.g. 123.0. For some clients this is unavoidable due to limitations in the programming language or libraries they are using. Unfortunately, DS rejects these values because they do not comply with the LDAP integer syntax. The following solution has been proposed in Rest2Ldap for converting incoming numeric JSON values to LDAP attributes:
- if the LDAP attribute has integer syntax then try to coerce the JSON value to an integer:
- if it is an Integer or related type (Short, Byte, etc) then convert it directly to an Integer
- if it is a real number (Float or Double) then only convert it if it is a whole number (e.g. 1.0). If it has a non-zero fractional part then reject the value since converting to an integer will lose information and hide a potential incompatibility with the client.
- otherwise, assume the LDAP syntax is some string related syntax, and convert the number to its string representation regardless of whether it's an integer or floating point number.
This does mean that in some cases user provided data will be modified when they read it back later. Specifically, any trailing .0 will be truncated when integers are expected.