Delphi SuperObject sorting values in a different order than added

2.1k views Asked by At

I'm using SuperObject to produce JSON. The server I'm working with has some specifications for sorting data results (the fact that this is related to sorting data has nothing to do with my actual question about sorting). The thing is, the server expects these values to be listed in order of how to sort, so for example...

"sort": {
  "first_sort_field": 1,
  "second_sort_field": 1,
  "third_sort_field": -1,
  "fourth_sort_field": 1
}

1 means ascending and -1 means descending. But that's not the important part. What's important is that these values in the sort object must be organized in this manner.

To produce this object, I'm doing this:

var
  O, O2: ISuperObject;
  X: Integer;
  //more
begin
  O:= SO; //main object

  //more

  O2:= SO; //sub object
  for X := 0 to FSort.Count - 1 do begin
    case FSort[X].Direction of
      sdAscending:  O2.I[FSort[X].FieldName]:= 1;
      sdDescending: O2.I[FSort[X].FieldName]:= -1;
    end;
  end;
  O.O['sort']:= O2;

  //more
end;

The problem arises when I use SuperObject to serialize this "sort" object. The values seem to be re-arranged, so for example the JSON above would actually come out something like this:

"sort": {
  "first_sort_field": 1,
  "fourth_sort_field": 1
  "second_sort_field": 1,
  "third_sort_field": -1,
}

Which is a different order than I intended. This causes the server to return the response data sorted in a different manner than intended.

The question is, how can I make SuperObject serialize the data in the order which I added it rather than its own order? I thought that it might be sorting the values in ABC order, but when combining different types of values (string, integer, object, array, etc.) they're not in ABC order. I'd like to force SuperObject to serialize the data in the order which I added it.

The only solution I can see is to serialize this object manually by concatenating strings. But I'd like to avoid that if at all possible - that's why I'm using SuperObject in the first place.

1

There are 1 answers

12
David Heffernan On BEST ANSWER

The documentation for JSON states that its dictionary object is unordered:

An object is an unordered set of name/value pairs. An object begins with { (left brace) and ends with } (right brace). Each name is followed by : (colon) and the name/value pairs are separated by , (comma).

By way of contrast, the JSON array is ordered:

An array is an ordered collection of values. An array begins with [ (left bracket) and ends with ] (right bracket). Values are separated by , (comma).

If you want to persist the order of your keys, you will need to do so separately from the dictionary. Any program that expresses meaning by the order in which name/value pairs are written falls outside the JSON spec. So, if your server relies on the order, then that makes the file no longer a JSON file.

Order is clearly important here. And so the solution is clear. Use the ordered data type, the array. Your JSON should be:

"sort": [
    { "name": "first_sort_field", "order": 1 },
    { "name": "second_sort_field", "order": 1 },
    .....
]