%DynamicObject: How to insert json property at a specific location?
Hi,
I know json does not impose any order, but for readability I would like to insert a json property at a specific location at the start of a %DynamicObject, not at the end.
Is there a known way to do that (other than string manipulation)?
Comments
/// Python reorder FHIR propertiesClassMethod PyFHIRResourceReOrder(resource As%String) As%String [ Language = python ]
{
import json
from collections import OrderedDict
result = json.loads(resource, object_pairs_hook=OrderedDict)
result.move_to_end("extension", last = False)
result.move_to_end("meta", last = False)
result.move_to_end("id", last = False)
result.move_to_end("resourceType", last = False)
return json.dumps(result)
}This Python code is what I ended up with. It re-orders the properties "resourceType", "id", "meta" and "extension" to be at the start
String manipulation under covers! ![]()
Yes, although the Python code does deal with an actual collection object :)
If you want to reorder JSON properties (alphabetically or just put some of them at the beginning) then use a utility method, like this, especially if you have several object(types) to reorder
Class DC.Utility Extends%RegisteredObject
{
/// Reorder a JSON Object or Array/// /// obj: JSON-Object/// ord: prop1, prop2, ... Desired order for (some) properties/// (Properties not listed are copied in the order in which they were created)/// If ord not present, properties will be reordered in aplphabetical order/// /// obj: JSON-Array/// ord: pos1, pos2, ... Desired order for (some) array items/// (Items not listed are copied in ascending order)/// ClassMethod ReOrder(obj As%DynamicAbstractObject, ord... As%String)
{
i obj.%Extends("%DynamicObject") {
snew={}, itr=obj.%GetIterator()
i '$g(ord) {
while itr.%GetNext(.k) { s done(k)=0 }
sk="" f sk=$o(done(k)) q:k=""dnew.%Set(k,obj.%Get(k))
} else {
f i=1:1:$g(ord) { sk=ord(i),done(k)=1d:$e(obj.%GetTypeOf(k),1,2)'="un"new.%Set(k,obj.%Get(k)) }
while itr.%GetNext(.k,.v) { d:'$d(done(k)) new.%Set(k,v) }
}
} elseif obj.%Extends("%DynamicArray") {
snew=[], itr=obj.%GetIterator(), max=obj.%Size(), done=""
f i=1:1:$g(ord) { sk=ord(i) i k,k<=max dnew.%Push(obj.%Get(k-1)) s$bit(done,k)=1 }
while itr.%GetNext(.k,.v) { d:'$bit(done,k+1) new.%Push(v) }
} else { snew=obj }
qnew
}
}Some examples
s car={"color":"red", "fuel":"diesel", "maxspeed":150, "maker":"Audi", "model":"Quattro Q5", "power":300, "available":true, "rating":8, "allWheel":true }
s car1=##class(DC.Utility).ReOrder(car) // order all props alphabeticallys car2=##class(DC.Utility).ReOrder(car,"maker","model","available") // start with maker, model, etc.w car.%ToJSON(),!,car1.%ToJSON(),!,car2.%ToJSON() --->
{"color":"red","fuel":"diesel","maxspeed":150,"maker":"Audi","model":"Quattro Q5","power":300,"available":true,"rating":8,"allWheel":true}
{"allWheel":"1","available":"1","color":"red","fuel":"diesel","maker":"Audi","maxspeed":150,"model":"Quattro Q5","power":300,"rating":8}
{"maker":"Audi","model":"Quattro Q5","available":"1","color":"red","fuel":"diesel","maxspeed":150,"power":300,"rating":8,"allWheel":"1"}Thanks, Julius, that is really helpful!!
I have implemented the part of the method that I needed as follows:
/// Move FHIR resourceproperties in the followin order:/// - resourceType/// - id/// - meta/// - extensionClassMethod FHIROrderResourceProperties(resource As%DynamicObject) As%DynamicObject
{
#dim order as%DynamicArray = [ "resourceType", "id", "meta", "extension" ]
#dim newObject as%DynamicObject = {}
for index = 0:1:order.%Size() - 1
{
set element = order.%Get(index)
set done(element) = 1if$EXTRACT(resource.%GetTypeOf(element), 1, 2) '= "un"
{
do newObject.%Set(element, resource.%Get(element))
}
}
set iterator = resource.%GetIterator()
while iterator.%GetNext(.element, .value)
{
if '$DATA(done(element))
{
do newObject.%Set(element, value)
}
}
return newObject
}