How do I create a JSON object that can handle conditionals?

advertisements

I would like to create a JSON object that can handle conditionals/branching. Specifically, I have a workflow like the following:

For step 1, the user has three choices, and depending on what choice they make, they are presented with a different set of choices for step 2. That same logic extends to step 3, etc.

Ideally, I'd like to have all this data in JSON format so that I can loop through it and based on a user's choice, figure out what choices I need to present to them next.

Is there a way to structure a JSON object (or perhaps just an array) in a way that will allow me to do this?

I should mention that I would like this to be flexible enough so that if I decided at a later time to change the number of choices for a step, then all I'd have to do is modify the JSON object/array (the model) without having to modify the logic that loops through the object/array.

Thank you very much.


What you are building is essentially a tree data structure. I would suggest building it from primitive node objects, than can contain recursive references to child objects of the same type. The tree can be implemented fully using only this one type of object, where the "topmost" object is called the root object, where all users start making their selections. Starting from the root, users select child nodes until they reach a leaf node that has no children, i.e. from where no further selections can be made.

All nodes are objects like this:

{
    "label": "Choice A",
    "question": "Choose subselection?",
    "children": [ (array of more objects of the same type) ]
}

Where label is the name / label you want to give to this option, question is next question users must answer to select the next child node, and children is an array of more of nodes of the same type, where each children's label is one possible answer to this node's question.

To demonstrate by example, let us assume the following selection tree, that could be asked in an imaginary online retailing store, that only sells two main types of products: clothing and food. In the clothing section, there are jeans, t-shirts and hoodies of different colors (for simplicity, let us assume we already know the customer's size.) The shop also carries a small selection of types of hats. In the food section, there are available ramen noodles, different flavors of soda, and bananas. In the clothing section, customers can have a logo of a TV show or a rock band printed on their black T-shirt, or just buy a plain black T-shirt without a logo. The logo of the TV-show can additionally be printed on a blue hoodie, or customers can choose to buy the blue hoodie without a logo.

So, the decision tree of answer/question pairs facing the customer is as follows:

A: <start>
Q: What product category?
|
|--A: Clothes
|  Q: What type of clothing?
|  |
|  |--A: Jeans
|  |  Q: Color of jeans?
|  |  |
|  |  |--A: Blue
|  |  |  Q: <end>
|  |  |
|  |  |--A: Black
|  |  |  Q: <end>
|  |  |
|  |  \--A: White
|  |     Q: <end>
|  |
|  |--A: Shirt
|  |  Q: Type of shirt?
|  |  |
|  |  |--A: T-shirt
|  |  |  Q: Color of T-shirt?
|  |  |  |
|  |  |  |--A: Red
|  |  |  |  Q: <end>
|  |  |  |
|  |  |  |--A: Green
|  |  |  |  Q: <end>
|  |  |  |
|  |  |  |--A: Black
|  |  |  |  Q: Logo?
|  |  |  |  |
|  |  |  |  |--A: Rock band
|  |  |  |  |  Q: <end>
|  |  |  |  |
|  |  |  |  |--A: TV show
|  |  |  |  |  Q: <end>
|  |  |  |  |
|  |  |  |  \--A: No logo
|  |  |  |     Q: <end>
|  |  |  |
|  |  |  \--A: Orange
|  |  |     Q: <end>
|  |  |
|  |  \--A: Hoodie
|  |     Q: Color of hoodie?
|  |     |
|  |     |--A: Gray
|  |     |  Q: <end>
|  |     |
|  |     |--A: Blue
|  |     |  Q: Logo for hoodie?
|  |     |  |
|  |     |  |--A: TV show
|  |     |  |  Q: <end>
|  |     |  |
|  |     |  \--A: No logo
|  |     |     Q: <end>
|  |     |
|  |     |--A: Green
|  |     |  Q: <end>
|  |     |
|  |     |--A: Pink
|  |     |  Q: <end>
|  |     |
|  |     |--A: Brown
|  |     |  Q: <end>
|  |     |
|  |     |--A: Black
|  |     |  Q: <end>
|  |     |
|  |     \--A: Red
|  |        Q: <end>
|  |
|  \--A: Hat
|     Q: Type of hat?
|     |
|     |--A: Stetson
|     |  Q: <end>
|     |
|     \--A: Sombrero
|        Q: <end>
|
\--A: Food
   Q: Type of food?
   |
   |--A: Ramen noodles
   |  Q: <end>
   |
   |--A: Soda pop
   |  Q: Flavor
   |  |
   |  |--A: Cola
   |  |--Q: <end>
   |  |
   |  |--A: Lemon
   |  |--Q: <end>
   |  |
   |  |--A: Orange
   |  |--Q: <end>
   |  |
   |  |--A: Apple
   |  \--Q: <end>
   |
   \--A: Bananas
      Q: <end>

Customers begin at the "answer" <start> and select multiple-choice questions until they reach a node with the special "question" <end>.

When we map this tree to JSON, the root question (<start> above) that asks the product category the user is interested in (clothes/foods) can have the label value of null, since it is not an answer (child) to any other question. It is the first object of the whole structure, and all other nodes are its children. The leaf nodes, where no further selections can be made (<end> above), are indicated by having null in place of the question string and the children array. All other nodes specify a label string (the top-level question the node "answers"), the next question, and an array of possible answers to the question:

{
 "label": null,
 "question": "What product category?",
 "children": [
  {
   "label": "Clothes",
   "question": "What type of clothing?",
   "children": [
    {
     "label": "Jeans",
     "question": "Color of jeans?",
     "children": [
      {
       "label": "Blue",
       "question": null,
       "children": null
      },
      {
       "label": "Black",
       "question": null,
       "children": null
      },
      {
       "label": "White",
       "question": null,
       "children": null
      }
     ]
    },
    {
     "label": "Shirt",
     "question": "Type of shirt?",
     "children": [
      {
       "label": "T-Shirt",
       "question": "Color of T-shirt?",
       "children": [
        {
         "label": "Red",
         "question": null,
         "children": null
        },
        {
         "label": "Green",
         "question": null,
         "children": null
        },
        {
         "label": "Black",
         "question": "Logo?",
         "children": [
          {
           "label": "Rock band",
           "question": null,
           "children": null
          },
          {
           "label": "TV show",
           "question": null,
           "children": null
          },
          {
           "label": "No logo",
           "question": null,
           "children": null
          }
         ]
        },
        {
         "label": "Orange",
         "question": null,
         "children": null
        }
       ]
      },
      {
       "label": "Hoodie",
       "question": "Color of hoodie?",
       "children": [
        {
         "label": "Gray",
         "question": null,
         "children": null
        },
        {
         "label": "Blue",
         "question": null,
         "children": [
          {
           "label": "TV show",
           "question": null,
           "children": null
          },
          {
           "label": "No logo",
           "question": null,
           "children": null
          }
         ]
        },
        {
         "label": "Green",
         "question": null,
         "children": null
        },
        {
         "label": "Pink",
         "question": null,
         "children": null
        },
        {
         "label": "Brown",
         "question": null,
         "children": null
        },
        {
         "label": "Black",
         "question": null,
         "children": null
        },
        {
         "label": "Red",
         "question": null,
         "children": null
        }
       ]
      },
      {
       "label": "White",
       "question": null,
       "children": null
      }
     ]
    },
    {
     "label": "Hat",
     "question": "Type of hat?",
     "children": [
      {
       "label": "Stetson",
       "question": null,
       "children": null
      },
      {
       "label": "Sombrero",
       "question": null,
       "children": null
      }
     ]
    }
   ]
  },
  {
   "label": "Food",
   "question": "Type of food?",
   "children": [
    {
     "label": "Ramen noodles",
     "question": null,
     "children": null
    },
    {
     "label": "Soda pop",
     "question": null,
     "children": [
      {
       "label": "Cola",
       "question": null,
       "children": null
      },
      {
       "label": "Lemon",
       "question": null,
       "children": null
      },
      {
       "label": "Orange",
       "question": null,
       "children": null
      },
      {
       "label": "Apple",
       "question": null,
       "children": null
      }
     ]
    },
    {
     "label": "Bananas",
     "question": null,
     "children": null
    }
   ]
  }
 ]
}

The above is 100% valid JSON: you can copy&paste it to JSONtree to investigate its structure level-by-level.

The morale of the story is, that this kind of a possibly quite complex system of available user selections and paths, can be implemented with a surprisingly simple data structure at its core (a node with leaves). The complexity arises from the relations that you define between the nodes.