PDA

View Full Version : Outputting key from a JSON file



kayut
02-06-2017, 04:31 PM
Hi,

If this is the JSON:



[
{
"question": "What's a Dog?",
"answer": "The domestic dog is a member of genus Canis that forms part of the wolf-like canids, and is the most widely abundant carnivore."
},
{
"question": "What’s an Elephant?",
"answer": "Elephants are large mammals of the family Elephantidae and the order Proboscidea. Two species are traditionally recognised, the African elephant and the Asian elephant, although some evidence suggests that African bush elephants and African forest elephants are separate species"
},
{
"question": "What's a Tiger ?",
"answer": "The tiger is the largest cat species, most recognisable for their pattern of dark vertical stripes on reddish-orange fur with a lighter underside. The species is classified in the genus Panthera with the lion, leopard, jaguar and snow leopard. Tigers are apex predators, primarily preying on ungulates such as deer and bovids."
}
]


I can access the value of each question and answer with this loop:



for (var i in data) {
result += '<div>' + data[i].question + '</div>';
result += '<div>' + data[i].answer + '</div>';
}


But how can I output the key of each property, which would be the strings "question" and "answer"?

PS: The purpose of this question is, to learn and understand how to have full control over outputting and working with a JSON file.

Thanks

jscheuer1
02-06-2017, 05:38 PM
Well, first of all, doing:


for (var i in data) {
result += '<div>' + data[i].question + '</div>';
result += '<div>' + data[i].answer + '</div>';
}

since data is an array, that's iteration over an array as if it's an object and can create an error or an unexpected result (if the array has any other properties besides its numerically indexed ones), though it can also often work as desired. It's better to use a:


for(var i = 0; i < data.length; ++i)

loop, or the more efficient while:


var i = -1, d = data.length;
while(++i < d)

loop.

Now the information you want (answer and question keys) are not contained in the array though, so to get at them, you need to iterate over the contained objects, but - as we have already seen in a previous question on similar code, doing both can create duplicate entries. But it doesn't have to. It's a little complex for me to explain, but, since I've worked out a way to do it, also taking care of some other issues I saw with the code, I'll just show you what I came up with:


<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
#container {
max-width: 500px;
}
.my-questdiv {
border: 2px inset #ddd;
font-family: sans-serif;
margin-bottom: 10px;
padding: 10px 15px;
background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAGNJREFUSIntzbENgDAMRNFfkR42YUxYBlLDSlkBGhcWSlJYToP86 9M9iKKo1wJswNTZJGAHZgtwAw9wNJAEZNlcFmAFSgPR50W2pjRyCuJ2XkOy93kNcT//IkPONTLsPIr+2gsEwx4NLAopngAAAABJRU5ErkJggg==');
background-position: 98% 50%;
background-repeat: no-repeat;
}

.my-ansdiv {
display: none;
margin-bottom: 15px;
padding: 10px;
background: #F2F2F2;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {

$.getJSON('faq.json', function(data){
var tags = ['<div class="my-questdiv">', '</div>', '<div class="my-ansdiv">', '</div>'],
i = c = -1, d = data.length, t = tags.length, $c = $('#container');
while (++i < d) {
for(var key in data[i]){
$c.append(tags[++c % t] + key + ': ' + data[i][key] + tags[++c % t]);
}
}

$('.my-questdiv').on('click', function() {
var $thisans = $(this).next('.my-ansdiv');
$('.my-ansdiv').not($thisans).slideUp();
$thisans.slideToggle();
});

}); //getJSON

}); // ready
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>

I changed the element for the questions to DIV because of the inconsistencies rendering the select across browsers, changed the styles to get a similar look for that div, and changed to a base 64 png image because it wasn't rendering as svg in all browsers. I also appended directly to the output element, changed the class names to reflect their usage, added the event after outputting the markup and made the event a little more complex, those last four aren't so important.

The real answer to your question is in the highlighted area. While iterating over the data array, each data[i] consists of an object with a question and an answer. Each question is keyed 'question' and each answer is keyed 'answer' so they're names can be gotten at that stage in the process by iterating over them using the for(var key in data[i]) loop. If you check the output, you will get something like:


question: What's a Dog?

and:


answer: The domestic dog is . . .

etc.

I'm not sure this is a really great idea though, because there's no requirement for the keys to be in the order expected, though all modern browsers I tested in did put them in that order. Even given that issue (older browsers might mix up the questions with the answers), one can still do this, as long as one tests for which key it is and puts the output where it belongs. But at that point, you once again have to know what the keys are anyway and use their literal names in the code, so you may as well just use them to get what you want when you want it, it's simpler.