Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Maintaining trailing zeros for decimal precision in json output #1497

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/export/InstanceExporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,15 @@
value = `#${matchingContainedReferenceId}`;
}
}
let rawValue = (rule instanceof AssignmentRule) ? rule.rawValue : null

Check failure on line 181 in src/export/InstanceExporter.ts

View workflow job for this annotation

GitHub Actions / Check tsc, lint, and prettier

'rawValue' is never reassigned. Use 'const' instead

Check failure on line 181 in src/export/InstanceExporter.ts

View workflow job for this annotation

GitHub Actions / Check tsc, lint, and prettier

Missing semicolon
const validatedRule = instanceOfStructureDefinition.validateValueAtPath(
rule.path,
value,
this.fisher,
inlineResourceTypes,
rule.sourceInfo,
manualSliceOrdering
manualSliceOrdering,
rawValue
);
// Record each valid rule in a map
// Choice elements on an instance must use a specific type, so if the path still has an unchosen choice element,
Expand Down
19 changes: 11 additions & 8 deletions src/fhirtypes/ElementDefinition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1830,7 +1830,7 @@ export class ElementDefinition {
* @throws {ValueAlreadyAssignedError} when the value is already assigned to a different value
* @throws {MismatchedTypeError} when the value does not match the type of the ElementDefinition
*/
assignValue(value: AssignmentValueType, exactly = false, fisher?: Fishable): void {
assignValue(value: AssignmentValueType, exactly = false, fisher?: Fishable, rawValue: any = null): void {
let type: string;
if (value instanceof FshCode) {
type = 'Code';
Expand Down Expand Up @@ -1870,7 +1870,7 @@ export class ElementDefinition {
this.assignFHIRValue(value.toString(), value, exactly, 'boolean');
break;
case 'number':
this.assignNumber(value as number, exactly);
this.assignNumber(value as number, exactly, rawValue);
break;
case 'string':
this.assignString(value as string, exactly);
Expand Down Expand Up @@ -2230,14 +2230,17 @@ export class ElementDefinition {
* @throws {ValueAlreadyAssignedError} when the value is already assigned to a different value
* @throws {MismatchedTypeError} when the value does not match the type of the ElementDefinition
*/
private assignNumber(value: number | bigint, exactly = false): void {
private assignNumber(value: number | bigint, exactly = false, rawValue: any = null): void {
const type = this.type[0].code;
const valueAsNumber = Number(value);
if (
type === 'decimal' ||
(type === 'integer' && Number.isInteger(valueAsNumber)) ||
(type === 'unsignedInt' && Number.isInteger(valueAsNumber) && valueAsNumber >= 0) ||
(type === 'positiveInt' && Number.isInteger(valueAsNumber) && valueAsNumber > 0)
// In case of
if (type === 'decimal' && !isNaN(Number(rawValue)) && /^\d+\.0+$/.test(rawValue)) {
this.assignFHIRValue(rawValue.toString(), rawValue.toString(), exactly, type);
} else if (
type === 'decimal' ||
(type === 'integer' && Number.isInteger(valueAsNumber)) ||
(type === 'unsignedInt' && Number.isInteger(valueAsNumber) && valueAsNumber >= 0) ||
(type === 'positiveInt' && Number.isInteger(valueAsNumber) && valueAsNumber > 0)
) {
this.assignFHIRValue(value.toString(), valueAsNumber, exactly, type);
} else if (type === 'integer64' && typeof value === 'bigint') {
Expand Down
5 changes: 3 additions & 2 deletions src/fhirtypes/StructureDefinition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,8 @@ export class StructureDefinition {
fisher: Fishable,
inlineResourceTypes: string[] = [],
sourceInfo: SourceInfo = null,
manualSliceOrdering = false
manualSliceOrdering = false,
rawValue: any = null
): { assignedValue: any; pathParts: PathPart[]; childPath?: string } {
const pathParts = parseFSHPath(path);
let currentPath = '';
Expand Down Expand Up @@ -773,7 +774,7 @@ export class StructureDefinition {
// assignValue will throw if it fails, but skip the check if value is null
if (value != null) {
// exactly must be true so that we always test assigning with the more strict fixed[x] approach
currentElement.assignValue(value, true, fisher);
currentElement.assignValue(value, true, fisher, rawValue);
}
// If there is a fixedValue or patternValue, find it and return it
const key = Object.keys(currentElement).find(
Expand Down
18 changes: 15 additions & 3 deletions src/utils/Processing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -564,9 +564,21 @@
)
) {
checkNullValuesOnArray(resource);
fs.outputJSONSync(path.join(exportDir, resource.getFileName()), resource.toJSON(snapshot), {
spaces: 2
});
const replacer = (key: any, value: string) => {
if (typeof value === "string" && !isNaN(Number(value))) {

Check failure on line 568 in src/utils/Processing.ts

View workflow job for this annotation

GitHub Actions / Check tsc, lint, and prettier

Strings must use singlequote
// Format the number while keeping the exact number of zeros after the decimal point
const numValue = Number(value);
return value.includes('.') ? numValue.toFixed(value.split('.')[1].length) : numValue;
}
return value;
};
const jsonString = JSON.stringify(resource.toJSON(snapshot), replacer, 2);

// Manually format the JSON string to maintain number type with precision
const formattedJsonString = jsonString.replace(/"(\d+\.\d+)"|"\d+"/g, (match) => match.replace(/"/g, ''));

// Write the modified JSON string directly to a file
fs.outputFileSync(path.join(exportDir, resource.getFileName()), formattedJsonString);
count++;
} else {
logger.error(
Expand Down
Loading