3

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.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Jerry Dodge
  • 26,858
  • 31
  • 155
  • 327

1 Answers1

6

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 },
    .....
]
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Thanks, it's just a matter of getting the server's author to change the specifications, luckily this server is still in early developments and is not used yet. Also, I don't see why you edited my question, the JSON specifically - your edits are identical to what I already had there :-) – Jerry Dodge Dec 03 '13 at 17:39
  • 1
    @JerryDodge I improved the visuals. In your original version the JSON was a code block and formatted as though it was Pascal. Which mean that parts between {} appeared as comments. By using a
     I avoided that. You can see what I mean here in your original version: http://stackoverflow.com/revisions/20340920/1
    – David Heffernan Dec 03 '13 at 17:49
  • The developer of the server thinks otherwise, and doesn't want to change this. He is using mongodb and claims that mongodb actually has this specification, and disagrees with your claim. I'm not saying you're wrong, I'm just wondering why mongodb would defy the rules of JSON? – Jerry Dodge Dec 03 '13 at 20:34
  • I'm not actually claiming anything. I've just quoted from json.org so it's them that are making claims, and who are we to argue with json.org?! I know nothing about mongodb. But if the semantics are that objects are ordered what you have is something that superficially looks like JSON but is in fact not JSON. – David Heffernan Dec 03 '13 at 20:43
  • Related: http://stackoverflow.com/questions/2774361/json-output-sorting-in-python – Jerry Dodge Dec 03 '13 at 20:47
  • Also related: http://stackoverflow.com/questions/13551224/jsonkit-how-to-keep-order-of-json-dictionary-keys – Jerry Dodge Dec 03 '13 at 20:48
  • There are millions of questions on this topic! – David Heffernan Dec 03 '13 at 20:48
  • Yup, here's another one too: http://obroll.com/how-to-sort-dictionary-by-keys-or-by-values-in-python/ but all the solutions are specific to other languages, I would need one specific to SuperObject. – Jerry Dodge Dec 03 '13 at 20:51
  • It depends on whether or not you want to use JSON, in which case you have nothing more to do, or whether you want to use your colleagues JSON-like format in which case you have to write your own emitter! Or find a JSON emitter that happens to emit in the order you want. – David Heffernan Dec 03 '13 at 21:09
  • So the issue is actually that mongodb uses `BSON` not `JSON` which appears to be proprietary to mongodb... – Jerry Dodge Dec 03 '13 at 22:10
  • @JerryDodge Well, I think it's more complex than that. What you posted here is not BSON though is it. It is text. And BSON is binary. – David Heffernan Dec 03 '13 at 22:15
  • Yeah, I had no idea this was a result of limitations in mongodb, which every day I hear of something horrible about it. For example, there's no such thing as data types. Client is responsible to know what type of data the server is going to send to it. A major shift from other SQL database engines. – Jerry Dodge Dec 03 '13 at 23:02