Which json structure is better for my requirements? - javascript

I want to store links and text. The links can be of image, video or gifs. And i want to store them in order the user specifies.
Ex: img1, some text, video, img2 - This should be saved as json.
So far I have come up with 2 options:
First:
{
"content": {
"0": ["image", "image-link-here"],
"1": ["text", "this is some text here"],
"2": ["image", "2nd-image-link"],
"3": ["video", "video-link"]
}
}
Second: In this case, i can know if its image, video, gif or text by extension
{
"content": ["https://somelink.com/pic.jpg", "this is a text", "https://somelink.com/pic2.png", "https://somelink.com/vid.mp4"]
}
I need to store these in DynamoDB. So which one would be good and correct keeping in mind that I expect DB to grow?
If both these approaches are bad, please suggest the good way to do it.

You should try to make arrays where each element has the same type/structure, as it will enable better searches.
The second solution is not specific enough. As a text could end with ".jpg", you'll need a more elaborate test to determine whether it is just text or not. The text might even look a lot like a URL...
The first is better, but it is not really helpful to have numerical keys. Instead you should combine per type, and use that type as the key name, and put the actual value(s) in an array value, like this:
{
"content": {
"images": ["image-link-here", "2nd-image-link"],
"texts": ["this is some text here"],
"videos": ["video-link"]
}
}
This structure should allow for most practical searches.
As you indicated in comments that you need to know the order of each item, then I would suggest to define content as an array, where the occurrence of elements in that array represent the order of them:
{
"content": [
{ "image": "image-link-here" },
{ "text": "this is some text here" },
{ "image": "2nd-image-link" },
{ "video": "video-link" }
]
}
Or, to make each of the objects have the same properties:
{
"content": [
{ "type": "image", "value": "image-link-here" },
{ "type": "text", "value": "this is some text here" },
{ "type": "image", "value": "2nd-image-link" },
{ "type": "video", "value": "video-link" }
]
}
The choice depends on which kind of queries you intend to do.

Related

jquery/ajax - how to iterate through a json message with duplicate keys?

I receive with my ajax post request a message with values to display. This json response message looks like this:
{
"line": {
"name": "Google item",
"images": {
"element": {
"order": "1",
"link": "https://google.com/1.jpg",
"name": "1.jpg"
},
"element": {
"order": "2",
"link": "https://google.com/2.jpg",
"name": "2.jpg"
},
"element": {
"order": "3",
"link": "https://google.com/3.jpg",
"name": "3.jpg"
},
"element": {
"order": "4",
"link": "https://google.com/4.jpg",
"name": "4.jpg"
},
"element": {
"order": "5",
"link": "https://google.com/5.jpg",
"name": "5.jpg"
}
},
"features": {
"element": {
"name": "1",
"order": "1"
},
"element": {
"name": "2",
"order": "2"
},
"element": {
"name": "3",
"order": "3"
},
"element": {
"name": "4",
"order": "4"
}
},
"purchasing_price": "10",
"selling_price": "20",
"ftp_path": "google/item",
"description": ""
}
}
I'm in development and have not so much experience with json in jquery/ajax.
I tried this:
function parseContent(content){
$("#name").val(content.line.name);
$("#ftp_path").val(content.line.ftp_path);
$("#html_description").val(content.line.description);
$("#feature").remove();
$.each(content.line.features, function(k, v){
$("#features").append('<input type="text" class="form-control mt-3" id="feature" value="' + v.name + '" required>');
alert(v.name );
});
}
My problem is, the variable content contains just the last image und feature element. But in chrome/network I could see, the complete message has been received.
So I found out there is a parsing issue: Parsed JSON contains only the last element.
But how can I fix this in my case, to iterate through all elements?
The JSON specification says:
The names within an object SHOULD be unique.
The names in those objects are not.
SHOULD means:
that there
may exist valid reasons in particular circumstances to ignore a
particular item, but the full implications must be understood and
carefully weighed before choosing a different course.
The implications here are that every JSON parser (that I'm aware of at least) will ignore all but one of the values with duplicate names in an object.
If you really need to deal with that data then you are going to have to either track down a parser which can handle it (I'm not aware of any) or write a custom JSON parser which can (you'll also need to decide what data structure you want to generate from it because JS can't have duplicate property names in objects either). There are a number of JSON parsers on npm you might want to examine the source code of as a starting point.
A better solution would be to change whatever is generating the source data to produce a sensible format that doesn't violate a SHOULD requirement. Replacing the duplicate property names with an array for example.

Adaptive Card show text input block based on choice set value

I have a card with input choice set of options a,b,others
If users selects option as "others" then an extra input text block should come below the choice set. Is this possible with "Only show when" element property
Here is my Adaptive Card JSON
{
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"body": [
{
"type": "Input.ChoiceSet",
"choices": [
{
"title": "a",
"value": "a"
},
{
"title": "b",
"value": "b"
},
{
"title": "c",
"value": "c"
},
{
"title": "Others",
"value": "Others"
}
],
"placeholder": "Select option"
},
{
"type": "Input.Text",
"placeholder": "Placeholder text",
"isVisible": false
},
{
"type": "ActionSet",
"actions": [
{
"type": "Action.Submit",
"title": "Submit"
}
]
}
]
}
and i'm using html with webchat-es5 javascript library for rendering the bot to a page.
All of the information you need in order to create a self-updating Adaptive Card in Web Chat using Adaptive Card extensibility can be found in this answer: BotFramework-WebChat - Adaptive Card
There are a few differences in your case that justify writing another answer:
You're using the CDN instead of the NPM package
You're using the ES5 bundle, which I'm assuming means you want this to work on IE11
You're trying to toggle visibility instead of change text
Just like in the other case, we need to define a naming schema for ourselves that we can use to identify the card elements our code needs to manipulate. I'm only using one keyword this time: "on."
{
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"body": [
{
"type": "Input.ChoiceSet",
"choices": [
{
"title": "a",
"value": "a"
},
{
"title": "b",
"value": "b"
},
{
"title": "c",
"value": "c"
},
{
"title": "Others",
"value": "Others"
}
],
"placeholder": "Select option",
"id": "main"
},
{
"type": "Input.Text",
"placeholder": "Placeholder text",
"isVisible": false,
"id": "on_main_Others"
},
{
"type": "ActionSet",
"actions": [
{
"type": "Action.Submit",
"title": "Submit"
}
]
}
]
}
Consider the choice set input to be our switch and the text input to be our target. The choice set input's ID is just the name we've picked for it (and all inputs should have ID's in order for the card to work anyway even if we're not using our own naming schema). The text input's ID takes the form on_<input>_<value> where <input> is the ID of our switch and <value> is the choice that makes the target visible.
Here's the code you can use to make that work (notice that it accommodates IE11 by not using any arrow functions, etc.):
AdaptiveCards.AdaptiveCard.onParseElement = function (element) {
const PREFIX_ON = 'on';
const segments = element.id && element.id.split('_');
if (segments && segments[0] == PREFIX_ON) {
const card = element.getRootElement();
const input = card.getElementById(segments[1]);
const targetValue = segments[2];
input.onValueChanged = function (sender) {
// The isVisible setter automatically updates the rendered elements
element.isVisible = (sender.value == targetValue);
};
}
};
Notice that we're accessing Adaptive Cards classes with an AdaptiveCards global variable. You may have guessed that this becomes available when you use the Adaptive Cards CDN. I need to warn you that unfortunately the latest version of the Adaptive Cards CDN is currently incompatible with the latest version of Web Chat. Adaptive Cards 2.x introduced breaking changes (which can be expected for a new major version), and Web Chat is currently using 1.2.6. To make sure your code works you should specify the version of the Adaptive Cards CDN in your HTML, and you might as well specify the version of Web Chat too in case newer versions of Web Chat come out later that break with Adaptive Cards 1.2.6.
<script crossorigin="anonymous" src="https://cdn.botframework.com/botframework-webchat/4.9.0/webchat-es5.js" ></script>
<script crossorigin="anonymous" src="https://unpkg.com/adaptivecards#1.2.6/dist/adaptivecards.js" ></script>
While it's unclear if you need to use the adaptiveCardsPackage property in Node, I'm pretty sure you do need to use it with the CDN:
WebChat.renderWebChat(
{
adaptiveCardsPackage: AdaptiveCards,
directLine: window.WebChat.createDirectLine({
secretOrToken: secretOrToken
})
},
document.getElementById('webchat')
);

Getiing field from JSON object in Javascript?

I want to extract the created_utc from the JSON object can anyone tell me how can I do that in javascript? I do not want to convert it into string and parse word by word is there a quicker method to obtain the created_utc field?
var temp = {
"responseHeader":{
"status":0,
"QTime":44,
"params":{
"q":"*:*",
"indent":"on",
"wt":"json",
"_":"1491759117819"}},
"response": {
"numFound": 2, "start": 0, "docs": [
{
"id": "1",
"_version_": 1564222440512421888
},
{
"author": ["illusorywall"],
"link_id": ["t3_3yy560"],
"created_utc": [1451606530],
"subreddit": ["bloodborne"],
"score": [5],
"body": ["I don't think it's always the same kind of wall. It can be a larger, sort of \"arched\" section of wall, or a small rectangular section of wall, like a normal doorway. I have seen these two spaces use the same texture though, if that's what you mean by it always being the same type of wall, but I think it can also have a different texture. I intend to take a screenshot of every one I find to be sure."],
"id": "4f9a4bc0-4b7b-4aba-8820-187bfd2e6645",
"_version_": 1564222753474609152
}]
}
};
You should be using:
temp.response.docs[1].created_utc[0]
Snippet:
var temp = {
"responseHeader": {
"status": 0,
"QTime": 44,
"params": {
"q": "*:*",
"indent": "on",
"wt": "json",
"_": "1491759117819"
}
},
"response": {
"numFound": 2,
"start": 0,
"docs": [{
"id": "1",
"_version_": 1564222440512421888
},
{
"author": ["illusorywall"],
"link_id": ["t3_3yy560"],
"created_utc": [1451606530],
"subreddit": ["bloodborne"],
"score": [5],
"body": ["I don't think it's always the same kind of wall. It can be a larger, sort of \"arched\" section of wall, or a small rectangular section of wall, like a normal doorway. I have seen these two spaces use the same texture though, if that's what you mean by it always being the same type of wall, but I think it can also have a different texture. I intend to take a screenshot of every one I find to be sure."],
"id": "4f9a4bc0-4b7b-4aba-8820-187bfd2e6645",
"_version_": 1564222753474609152
}
]
}
};
console.log(temp.response.docs[1].created_utc[0])
try this
temp["response"]["docs"][1]["created_utc"][0]

Using ng-repeat with keys in an array

I have an object, simulating a Cassandra database, where I retrieve its data to display it on a AngularJs app. Unfortunately, I can't make a premade header for my array because the keys are subject to change, depending on the data I'll retrieve (Here's an example of what I'm talking about):
var columnFamilyData = {
"DocInfo": {
"4c58abf5": {
"name": "coucou",
"extension": "pdf",
"size": 8751,
"type": "facture",
"repository": "archive"
},
"8cd524d7a45de": {
"name": "gerard",
"extension": "xml",
"size": 48734,
"type": "compta",
},
"5486d684fe54a": {
"name": "splendide",
"extension": "tiff",
"type": "photos",
"METADATA_A": "jambon"
}
},
"Base": {
"BASE_A": {
"name": "BASE_A",
"description": "That base is truly outrageous, they are truly, truly outrageous",
"baseMetadata_1": "METADATA_A",
"baseMetadata_2": "METADATA_B",
"baseMetadata_3": "METADATA_C"
},
},
}
As you can see, the arrays in DocInfo and Base are different, data and keys.
What I want to do is being able to use my ng-repeat to create a <th> line with the key name (for instance, Extension, of METADATA_A), but only once, since ng-repeat may duplicate this information.
I'm also providing a JSFiddle, if it can help any of you to understand my goal.
Thanks for reading and/or answering, have a great day.
Question is not totally clear, but it seems like you want "(key, val) in object" syntax.
ng-repeat="(name, age) in {'adam':10, 'amalie':12}"

Backbone.js design pattern for JSON data

I've got a question about best practice when designing JSON file which will be displayed by Backbone.js. I know that Backbone is completly agnostic in this topic, but maybe someone will give me good advice in this certain situation.
In the end, I need to have some views which will look like this
On 4th of July, in _____ we calebrate ____ day.
___ means a gap in text, where I'll have an text input or select (depends on type) which correctness will be verified.
So, I need to have a JSON file that describes that piece of text.
I thought about something like this
"body": [
{
"preInputText": "On 4th of July, in ",
"postInputText": "",
"answersID": ["1", "2"]
},
{
"preInputText": "we calebrate ",
"postInputText": " day",
"answersID": ["3"]
}
]
"answers": [
{
"ID": "1",
"content": "USA",
"correct": true
},
{
"ID": "2",
"content": "Canada",
"correct": false
},
{
"ID": "3",
"content": "Independent",
"correct": true
}
]
or, maybe simpleier, but not-so-flat
"body": [
{
"preInputText": "On 4th of July, in ",
"postInputText": "",
"answers": [
{
"ID": "1",
"content": "USA",
"correct": true
},
{
"ID": "2",
"content": "Canada",
"correct": false
},
]
}
]
etc…
So, first approach enforce creating two collections, passing them into one view, and checking values beetween them.
The second, just one collection of models that contains both body and answers, but parsing them at initialization and using nested construction.
I don't know is it a bad pratice (to use nested models), but as i read backbone was designed to think in the more flat way.
Maybe there is some kind of another logic? What do you think?
Thanks!
I'm more with the first approach (the flat one) and I don't agree with you that it enforce creating two collections.
You can always create a single collection and override it's parse function, something like this :
var MyCollection = Backbone.Collection.extend({
...
parse: function(resp) {
this.answers = new Backbone.Collection(resp.answers);
return resp.body;
}
});
...
// myCollection is an instance of MyCollection
myCollection.models // refer to questions
myCollection.answers // refer to answers
"body": [
{
"preInputText": "On 4th of July, in ",
"postInputText": "",
"answers" [ { "ID": "1", "content": "USA", "correct": "true"},
{ "ID": "1", "content": "canada", "correct": "false"}
]
},
{
"preInputText": "we calebrate ",
"postInputText": " day",
"answersID": [{ "ID": "3", "content": "Independent", "correct": "true"},
]
}
]
Using this structure, you need to use one collection. Then you can treat each object in this as a model and you can render these using their separate views in a collection view. So need to use nested models here

Categories