I am attempting to append a JSON element to an already existing array in my database. I know about jsonb_set however I can't upgrade to Postgres 9.4 as this is a groovy project and the latest postgresql version on Maven is 9.4.
I currently have a json structure like this:
"playersContainer": {
"players": [
{
"id": "1",
"name": "Nick Pocock",
"teamName": "Shire Soldiers",
"bio" : "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla imperdiet lorem tellus, in bibendum sem dignissim sed. Etiam eu elit sit amet lacus accumsan blandit sed ut dolor. Mauris vel dui non nisi vestibulum commodo vel id magna. Donec egestas magna in tincidunt mollis. Fusce mauris arcu, rhoncus ut lacus sed, fermentum ultrices elit. In sollicitudin at ex dapibus vestibulum. Pellentesque congue, est id lobortis viverra, mauris lectus pharetra orci, ut suscipit nisl purus vehicula est. Aliquam suscipit non velit vel feugiat. Quisque nec dictum augue.",
"ratings": [
1,
5,
6,
9
],
"assists": 17,
"manOfTheMatches": 20,
"cleanSheets": 1,
"data": [
3,
2,
3,
5,
6
],
"totalGoals": 19
}
}
I want to append new players to the player array and update my database, I tried doing an update but it wiped the rest of the data. Is there a way to target the players array and append the new json object to it?
Unfortunately 9.4 does not have json_set function. You can use something like this:
WITH old_players AS (
SELECT $1 AS j
), new_player AS (
SELECT $2 AS j
), all_players AS (
SELECT json_array_elements(j->'playersContainer'->'players') AS p
FROM old_players
UNION ALL
SELECT *
FROM new_player
) SELECT ('{"playersContainer": {"players": ' || json_agg(p) || '}}')::json
FROM all_players
;
You can use it as function:
CREATE OR REPLACE FUNCTION add_player(old_player json, new_player json) RETURNS json AS $$
WITH all_players AS (
SELECT json_array_elements(($1)->'playersContainer'->'players') AS p
UNION ALL
SELECT $2
)
SELECT ('{"playersContainer": {"players": ' || json_agg(p) || '}}')::json
FROM all_players
$$ LANGUAGE sql IMMUTABLE;
And after that you can just call it :
UPDATE site_content SET content = add_player(content, '{"id": "2", "name": "Someone Else"}') where id = :id;
Related
I am trying to write code so that each time the confirm answer button is clicked, the next question in the json array is called. There are five questions in this file and so far I can get the first and second question to appear. Is there anyway I could write a loop so that the next question is called each time the user enters confirm?
I am new to swiftui and so am unsure about how to proceed
import SwiftUI
struct SecondView: View {
var ResearchMCQ: Question
//Creating Variables for Revision Topics
#State private var setOptionOne = false
#State private var setOptionTwo = false
#State private var setOptionThree = false
let button = ["Confirm Answer"]
#State public var buttonConfirm: Int?
var body: some View {
ScrollView{
VStack(spacing: 1.0) {
Group {
Text(ResearchMCQ.question)
.padding(.trailing, 5)
//Ensures Only One Answer Can Be Selected
let OptionOne = Binding<Bool>(get: { self.setOptionOne }, set: { self.setOptionOne = $0; self.setOptionTwo = false; self.setOptionThree = false })
let OptionTwo = Binding<Bool>(get: { self.setOptionTwo }, set: { self.setOptionOne = false; self.setOptionTwo = $0; self.setOptionThree = false })
let OptionThree = Binding<Bool>(get: { self.setOptionThree }, set: { self.setOptionOne = false; self.setOptionTwo = false; self.setOptionThree = $0 })
VStack {
Toggle(ResearchMCQ.options[0], isOn: OptionOne)
.toggleStyle(.button)
.tint(Color(.gray))
.foregroundColor(Color("Black-White"))
Toggle(ResearchMCQ.options[1], isOn: OptionTwo)
.toggleStyle(.button)
.tint(Color(.gray))
.foregroundColor(Color("Black-White"))
Toggle(ResearchMCQ.options[2], isOn: OptionThree)
.toggleStyle(.button)
.tint(Color(.gray))
.foregroundColor(Color("Black-White"))
}
}
Spacer()
Spacer()
HStack(spacing: 15) {
ForEach(0..<button.count, id: \.self) {button in
Button(action: {
self.buttonConfirm = button
}) {
//Links Continue Button To Next Page
NavigationLink(destination: SecondView(ResearchMCQ: questions[1])) {
Text("Confirm Answer")
}
.padding(.vertical, 12.5)
.padding(.horizontal, 120)
.foregroundColor(.white)
.foregroundStyle(.background)
.background(2 == button ? Color.primary: Color.secondary)
.clipShape(Capsule())
}
}
}
}
.navigationTitle("")
}
}
}
struct SecondView_Previews: PreviewProvider {
static var previews: some View {
SecondView(ResearchMCQ: questions[0])
}
}
If all questions have a similar structure, there are a couple of ways to achieve that.
For example, in the parent view you can iterate through the array of questions and call each time SecondView with a different question. I recommend that approach.
Because you didn't provide the parent view code, I propose here below a way to iterate through the array directly in SecondView.
You can change the same view instead of navigating to another one. So, SecondView should hold all questions, not just one, and you change the index of the question you are showing.
The steps to follow are here below:
Have your view holding the whole array of questions and not only one question. By the way, in Swift variables are lower caps.
// Remember to pass the whole array of questions to this variable
let researchMCQ: [Question]
Have another variable to hold the current question.
#State private var questionIndex = 0
Also buttonConfirm should be an array in this case.
#State public var buttonConfirm = [Int?]()
Show the current question (see how the variable researchMCQ is used here).
Group {
Text(researchMCQ[questionIndex].question)
.padding(.trailing, 5)
The confirmation button doesn't need a NavigationLink, just change the index and the next question will be shown.
Button {
buttonConfirm.append(button)
// or this, if you initialize the var with the whole array:
// buttonConfirm[questionIndex] = button
// Make sure the index doesn't go beyond the array size
if researchMCQ.count > questionIndex + 1 {
questionIndex += 1
}
} label: {
Text("Confirm Answer")
}
You can use a #Statevar to remember the active index of your questions, and then just count up this index. By doing so there is no need for further views.
Usually you would count through the questions from a parent view and then have the child view display one single question (and answers).
struct Question: Identifiable {
let id = UUID()
var question: String
var options: [String] = ["One", "Two", "Three"]
}
struct ContentView: View {
// dummy data
let researchMCQ: [Question] = [
Question(question: "First Question: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa qui"),
Question(question: "Second Question: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa qui"),
Question(question: "Third Question: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa qui"),
Question(question: "Fourth Question: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa qui")
]
// currently active question index
#State private var activeQuestionIndex = 0
//picked Option/Answer
#State private var pickedOption = 0
var body: some View {
VStack(spacing: 1.0) {
Group {
Text(researchMCQ[activeQuestionIndex].question)
.padding(.bottom)
Picker("Select Answer", selection: $pickedOption) {
Text(researchMCQ[activeQuestionIndex].options[0]).tag(0)
Text(researchMCQ[activeQuestionIndex].options[1]).tag(1)
Text(researchMCQ[activeQuestionIndex].options[2]).tag(2)
}
.pickerStyle(.segmented)
}
Spacer()
Button(action: {
if activeQuestionIndex < researchMCQ.count-1 {
self.activeQuestionIndex += 1
self.pickedOption = 0
}
}) {
Text("Confirm Answer")
}
.padding(.vertical, 12.5)
.padding(.horizontal, 120)
.foregroundColor(.white)
.foregroundStyle(.background)
.background(Color.primary)
.clipShape(Capsule())
}
.padding()
}
}
Hellog guys , i am trying to convert json data to object array for add these data to kendo grid but i am getting this error
Uncaught (in promise): TypeError: Cannot read property 'slice' of undefined
This error mean my data format isn't correct !.
This how data in json file are :
[
{
"orderNumber": 1,
"orderTable": "905503111-9",
"orderDescription": "Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.",
"orderDate": "5/4/2018",
"orderPrice": 79
}
]
But i want them to be like this :
{
"data": [
{
"orderNumber": 1,
"orderTable": "905503111-9",
"orderDescription": "Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.",
"orderDate": "5/4/2018",
"orderPrice": 79
}
],
}
Here an example of how i am accessing json file (orders.ts)
import { orders } from './orders';
import { employees } from '../employee/employees';
#Component({
selector: 'app-order',
templateUrl: './order.component.html',
styleUrls: ['./order.component.css']
})
export class OrderComponent implements OnInit {
public result;
public data = orders;
}
I tried many solutions like json.parse() and json.stringify() but didn't get what i need.
Note : I am using json file (orders.ts) that exist in my project.
var data = [
{
"orderNumber": 1,
"orderTable": "905503111-9",
"orderDescription": "Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.",
"orderDate": "5/4/2018",
"orderPrice": 79
}
];
var newData = {
"orderNumber": 1,
"orderTable": "905503111-9",
"orderDescription": "Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.",
"orderDate": "5/4/2018",
"orderPrice": 79
};
data.push(newData)
console.log(newData);
you can do it simply like this and make sure name is same as data
data=[
{
"orderNumber": 1,
"orderTable": "905503111-9",
"orderDescription": "Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.",
"orderDate": "5/4/2018",
"orderPrice": 79
}
];
let d={data}
console.log(d)
or
let d={}
d.data=[
{
"orderNumber": 1,
"orderTable": "905503111-9",
"orderDescription": "Nullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.",
"orderDate": "5/4/2018",
"orderPrice": 79
}
]
console.log(d)
you will get the desired output
I'm trying to insert data into my firebase JSon, which has the following structure
{
"gerechten" : [ {
"id" : "1",
"name" : "spaghetti",
"description" : "Spaghetti bolognese met veel liefde gemaakt op grootmoeders wijze.",
"kind" : "Pasta",
"preparation" : "1)Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?",
"img" : "../../assets/img/gerechten/spaghetti.jpg",
"ingredients" : [ "5kg wortelen", "3 aardappelen", "1 komkommer", "2 eieren", "3 eetlepels bloem", "50g zout" ]
} ]
}
as you see, i got an array 'gerechten" and inside each array another array "ingredients". Right now i can add a items but i have no idea how to fill my "ingredients".
Is there a way to let the user give inputs and with each ',' there is a new ingredient? Eq;
5 eggs, 2 appels, 1 spoon of suger
sould create
"ingredients" : ["5 eggs", "2 appels", "1 spoon of suger"]
Also, as of now I have to insert my id manually, how can I make it so it takes automatic the next ID? when I leave the ID empty I got this result:
Firebase arror
Its does not put it inside an array
this is how i do it at the moment:
create.ts:
gerecht = {
description: "",
kind: "",
name: "",
prepartion: "",
ingredients: "",
id: "",
img: ""
}
create() {
this.db.create(this.gerecht.id, this.gerecht.description, this.gerecht.kind, this.gerecht.name, this.gerecht.prepartion, this.gerecht.img, this.gerecht.ingredients)
this.navCtrl.push(HomePage)
}
firedataservice:
create(id: string, description: string, kind: string, name: string, preparation: string, img: string, ingredients: string) {
this.db.object('gerechten/'+id).update({
id: id,
description: description,
kind: kind,
name: name,
preparation: preparation,
img: img,
ingredients: ingredients
})
}
Instead of returning an array of objects, pulling from a JSON file, it returns an array of 4 arrays containing 4 objects? Why? JSON file name is portfolios.json.
'use strict';
var portfolioArray = [];
function Portfolio (portfoliosDataObj) {
this.title = portfoliosDataObj.title;
this.body = portfoliosDataObj.body;
this.img = portfoliosDataObj.img;
}
Portfolio.prototype.toHtml = function() {
var renderPortfolios = Handlebars.compile($('#portfolio-template').text());
return renderPortfolios(this);
console.log(this);
};
$.getJSON('/data/portfolios.json', function(portfolios) {
portfolios.forEach(function(portfoliosDataObject) {
var portfolio = new Portfolio(portfoliosDataObject);
portfolioArray.push(portfolios);
console.log(portfolios);
});
});
function print () {
portfolioArray.forEach(function(data) {
$('#portfolioSection').append(data.toHtml());
});
}
Portfolio();
print();
JSON FILE - Adding for reference.
[{
"title": "CodeFellows/Code201",
"body": "content1",
"img": ""
},
{
"title": "CodeFellows/Code301",
"body": "lorem ipsum"
},
{
"title": "Upcoming Projects/Other interest",
"body": "lorem impsum",
"img": "/images/blog.jpg"
},
{
"title": "Illustrations",
"body": "lorem ipsum",
"img": "/images/portfolio.png"
}]
IGNORE need more content that isn't code to post....
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam porttitor leo at tellus facilisis, id suscipit ipsum suscipit. Aenean venenatis, quam semper efficitur hendrerit, odio diam condimentum odio, id sagittis lorem tellus vel mauris. Cras enim neque, malesuada sit amet lacinia et, ullamcorper non sapien. Integer id hendrerit nulla, vitae tristique tortor. Aenean in arcu eget massa pulvinar dictum. Aliquam dictum fermentum sapien id iaculis. Ut malesuada varius lacinia. Maecenas scelerisque facilisis mattis.
The file returns an array of 4 objects, and not arrays.
{
"title": "CodeFellows/Code201",
"body": "content1",
"img": ""
}
is a javascript object, not an array (notice the curly braces {}).
The outer one is an array. (notice the square brackets[]).
You can get to the objects by doing a console.log(portfolios[0]);
The issue is with this code. You are pushing portfolios in portfolioArray instead of portfolio. Also you were doing console.log for portfolios which is why it was showing 4 arrays. I have fixed the code. Let me know if it works for you.
$.getJSON('/data/portfolios.json', function(portfolios) {
portfolios.forEach(function(portfoliosDataObject) {
var portfolio = new Portfolio(portfoliosDataObject);
portfolioArray.push(portfolio);
console.log(portfolio);
});
});
I'm trying to sort an array of characters in C. My bubble sort algorithm is a standard one but when I try to print the arrays after using the sort method they appear to be empty.
Is this a problem with my pointer usage?
#include <stdio.h>
#include <string.h>
char Gstr1[256];
char Gstr2[256];
void load();
void printArrays();
void sortArray(char *array);
main()
{
load();
printArrays();
sortArray(&Gstr1[0]);
sortArray(&Gstr2[0]);
printf("\n\n");
printArrays();
}
void load()
{
memcpy (Gstr1,"Sed aliquam neque fermentum leo semper sagittis. Curabitur imperdiet, libero vulputate laoreet tristique, magna justo posuere, quis rutrum ligula tortor vitae eros. Phasellus sed dignissim elit, nec dictum ligula. Vivamus ornare ultrices odio eget dictum.",255);
memcpy (Gstr2,"Lorem ipsum dolor si amet, consectetur adipiscing elit. Aenean dapibus libero a convallis sodales. Mauris placerat nisl leo, vitae tincidunt turpis tristique in. Pellentesque vehicula nisl vitae efficitur ornare. Nunc imperdiet sem, in aliquam rhoncus at.",255);
}
void printArrays()
{
printf(Gstr1);
printf("\n\n");
printf(Gstr2);
}
void sortArray(char *array)
{
int i,j;
char temp;
for(i=0;i<(256-1);i++)
for(j=0;j<(256-i-1);j++)
{
if((int)*(array+j)>(int)*(array+(j+1)))
{
temp=*(array+j);
*(array+j)=*(array+(j+1));
*(array+(j+1))=temp;
}
}
}
This is because of the string length. The length of first string is 256 and second is 257, and you're not taking care of '\0' character. Hence, it is advisable to use memcpy_s() instead of memcpy() and also, use strlen() instead of hardcoding the array size in the for loops. However, with minor correction of the for loop limit, the following code produces the output.
Code:
#include <stdio.h>
#include <string.h>
char Gstr1[256];
char Gstr2[256];
void load();
void printArrays();
void sortArray(char *array);
main()
{
load();
printArrays();
sortArray(&Gstr1[0]);
sortArray(&Gstr2[0]);
printf("\n\n");
printArrays();
}
void load()
{
memcpy (Gstr1,"Sed aliquam neque fermentum leo semper sagittis. Curabitur imperdiet, libero vulputate laoreet tristique, magna justo posuere, quis rutrum ligula tortor vitae eros. Phasellus sed dignissim elit, nec dictum ligula. Vivamus ornare ultrices odio eget dictum.",255);
memcpy (Gstr2,"Lorem ipsum dolor si amet, consectetur adipiscing elit. Aenean dapibus libero a convallis sodales. Mauris placerat nisl leo, vitae tincidunt turpis tristique in. Pellentesque vehicula nisl vitae efficitur ornare. Nunc imperdiet sem, in aliquam rhoncus at.",255);
}
void printArrays()
{
printf(Gstr1);
printf("\n\n");
printf(Gstr2);
}
void sortArray(char *array)
{
int i,j;
char temp;
for(i=0;i<strlen(array);i++)
for(j=0;j<(strlen(array)-i-1);j++)
{
if((int)*(array+j)>(int)*(array+(j+1)))
{
temp=*(array+j);
*(array+j)=*(array+(j+1));
*(array+(j+1))=temp;
}
}
}
You sort the last character in the array as well resulting in a sorted character array with leading null terminator.
Therefore just adjust your loops to fix your issue as shown below.
Of course it would be better to pass the array size with a parameter but that's a different topic :)
void sortArray(char *array)
{
int i,j;
char temp;
for(i=0;i<(256-2);i++)
for(j=0;j<(256-i-2);j++)
{
if((int)*(array+j)>(int)*(array+(j+1)))
{
temp=*(array+j);
*(array+j)=*(array+(j+1));
*(array+(j+1))=temp;
}
}
}