3

There a lot's of SO questions asking "how" to get unknown JSON keys from a JSON object, and I've done it plenty of times, but after starting to use JSON schema to start designing API request and responses, I am starting to question if having unknown or even dynamic keys that the JSON consumer has to be smart enough to know how to use.

For example, assume you are designing a simple graphing API for a bar graph. You could tell your consumer that you are just going to send them data in this format:

"data": {
  "Sunday": 1,
  "Monday": 2, 
  "Tuesday": 3,
  "Wednesday": 4,
  "Thursday": 5,
  "Friday": 6,
  "Saturday": 7
}

Technically, this is enough to create a graph where the labels on the x-axis are the keys in this JSON object, and the numbers are the scalars graphed on the y-axis. It's also technically dynamic, as you could create a whole new graph with the same pattern:

"data": {
  "Jack": 1,
  "Jill": 2,
  "Alice" 3
}

While JSON allows for flexibility, I'm beginning to question the usability of this. It feels like the equivalent of treating variable names in a Java class as a way of sending information.

An alternative approach might be to define a datapoint schema or something like this:

"data": [
  {
    "category": "Jack",
    "value": 1
  },
  {
    "category": "Jill",
    "value": 2
  },
  {
    "category": "Alice",
    "value": 3
  }
]

Additionally, this seems more extensible as well, as additional values can be added to the schema. However, it there is probably less marshaling and it's probably a bit easier to just use the unknown keys approach.

It just got me wondering, I have used unknown keys on the past, but they suddenly don't seem like the best approach.

  1. Are using unknown keys an intended use case for JSON? Or just a side affect that is being taken advantage of?
  2. Are there any best practices that promote or discourage the use of unknown keys?
  3. If there are any best practices for using unknown keys, under what conditions are they recommended?
6

Are using unknown keys an intended use case for JSON? Or just a side affect that is being taken advantage of?

In the case of your first two examples, it's the latter. The data is being put into a JSON object, which is an unordered structure. This lack of order makes these two bits of JSON equivalent, even if the one on the right doesn't lay out the bars on your chart as you intended:

"data": {           "data": {
  "Jack": 1,          "Alice": 3,
  "Jill": 2,          "Jack": 1,
  "Alice" 3           "Jill": 2
}                   }

You could write a JSON parser that will preserve the order of the members, but anything else processing it before you see it isn't likely to do the same. (ECMA 404 says nothing about order or uniqueness, but most parsers represent JSON objects as dictionaries that force this behavior.)

If there are any best practices for using unknown keys, under what conditions are they recommended?

The best practice is to use them as they were intended, which is in situations where you need to look up a value by name:

{
    "ssh": 22,
    "smtp": 25,
    "dns": 53,
    "http": 80
}

The implications of a structure that stores values by key are that the keys are unique and order doesn't matter. If you don't know what the keys are ahead of time, you can still answer questions like "what are the keys?" by iterating over them and, having answered that, use what you learned to fetch the values.

Your third example is the correct way to structure the data. The array imposes order on the bars in your graph. The (unordered) objects inside have members whose order doesn't matter because anything using them will be looking for them by name.

  • This answer is insightful. You are correct that I completely missed the concept of order in my first two examples. Your example using communication protocols and their ports suggests an object where the keys are known. So you do call out that unknown keys don't work for objects that are intended to be ordered, but does not answer whether there is a best practice under which they should be used. – rhamilton Aug 25 '17 at 6:03
  • @rhamilton If you're looking for a "best practice is always to do X" answer, I don't write those. I did edit the answer to address the don't-know-ahead-of-time case. – Blrfl Aug 25 '17 at 12:26
0

JSON can be used quite well to represent three basic data structures: Arrays, Dictionaries, and C-style structs. Arrays are represented by JSON arrays, Dictionaries and structs are represented by JSON "objects" (the JSON standard calls dictionaries "objects"). The only difference is that when representing structs, you often have many, many dictionaries with the same set of keys.

Your "alternative approach" just makes matters more difficult. Most languages come with a standard library that makes lookup in an array slow, and lookup in a dictionary fast. So your alternative approach either turns a dictionary into an array, wasting space and more importantly wasting speed, or forces the client developer to extract the dictionary manually from the JSON array (and in that cases, the redundancy cause you trouble - what if your array contains a dictionary with different keys? )

The argument "it's more extensible" is wrong. A dictionary consists of key-value pairs. The values can be dictionaries (this time dictionaries containing structs).

  • While everything you say here is true, you've missed the huge disadvantage pointed out in the other answer: JSON objects are not considered to be an ordered dictionary. A parser is therefore free to use them to populate a completely unordered structure - such as the JavaScript objects they're inspired by. That would clearly not be suitable for the graph axes given as an example in the question. – IMSoP Aug 24 '17 at 23:04
  • It is my assumption that JSON is generally used to send or pass data between more than one party and generally represents a contract. Under this assumption if I create a property in a JSON object that starts off as a key:string, but later needs additional information and becomes a key:object, I have just lost backwards compatibility in my contract. However, although I have made this assumption, and have used a graphing API as an example, I am looking for general JSON principles and would be interested other examples to consider. – rhamilton Aug 25 '17 at 6:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.