Is there a better way to extract values from this JSON? - arrays

I have found this example in https://www.sqlshack.com/extract-scalar-values-from-json-data-using-json_value/
DECLARE #data NVARCHAR(4000);
SET #data = N'{
"Employees": [
{
"EmpName": "Rohan Sharma",
"Department": "IT",
"Address": "101, Sector 5, Gurugram, India",
"Salary": 100000
},
{
"EmpName": "Manohar Lal",
"Department": "Human Resources",
"Address": "17, Park Avenue, Mumbai, India",
"Salary": 78000
}
]
}';
SELECT JSON_VALUE(#data, '$.Employees[0].EmpName') AS 'Name',
JSON_VALUE(#data, '$.Employees[0].Department') AS 'Department',
JSON_VALUE(#data, '$.Employees[0].Address') AS 'Address',
JSON_VALUE(#data, '$.Employees[0].Salary') AS 'Salary'
UNION ALL
SELECT JSON_VALUE(#data, '$.Employees[1].EmpName') AS 'Name',
JSON_VALUE(#data, '$.Employees[1].Department') AS 'Department',
JSON_VALUE(#data, '$.Employees[1].Address') AS 'Address',
JSON_VALUE(#data, '$.Employees[1].Salary') AS 'Salary'
So I wonder if there are better ways to get all values in JSON without telling $.Employees indexes?
Example, if I have N components in this JSON, I don't want to have to UNION ALL N times.
In my project there will be like more than 40 components in a single JSON.
DECLARE #data NVARCHAR(4000);
SET #data = N'{
"Employees": [
{
"EmpName": "Rohan Sharma",
"Department": "IT",
"Address": "101, Sector 5, Gurugram, India",
"Salary": 100000
},
{
"EmpName": "Manohar Lal",
"Department": "Human Resources",
"Address": "17, Park Avenue, Mumbai, India",
"Salary": 78000
},
{
"EmpName": "Emp 03",
"Department": "Demo",
"Address": "Address03",
"Salary": 9999
},
{
"EmpName": "Emp 04",
"Department": "Demo",
"Address": "Address04",
"Salary": 9999
},
{
"EmpName": "Emp N",
"Department": "Demo",
"Address": "AddressN",
"Salary": 9999
}
]
}';
SELECT JSON_VALUE(#data, '$.Employees[0].EmpName') AS 'Name',
JSON_VALUE(#data, '$.Employees[0].Department') AS 'Department',
JSON_VALUE(#data, '$.Employees[0].Address') AS 'Address',
JSON_VALUE(#data, '$.Employees[0].Salary') AS 'Salary'
UNION ALL
SELECT JSON_VALUE(#data, '$.Employees[1].EmpName') AS 'Name',
JSON_VALUE(#data, '$.Employees[1].Department') AS 'Department',
JSON_VALUE(#data, '$.Employees[1].Address') AS 'Address',
JSON_VALUE(#data, '$.Employees[1].Salary') AS 'Salary'
UNION ALL
SELECT JSON_VALUE(#data, '$.Employees[2].EmpName') AS 'Name',
JSON_VALUE(#data, '$.Employees[2].Department') AS 'Department',
JSON_VALUE(#data, '$.Employees[2].Address') AS 'Address',
JSON_VALUE(#data, '$.Employees[2].Salary') AS 'Salary'
UNION ALL
SELECT JSON_VALUE(#data, '$.Employees[3].EmpName') AS 'Name',
JSON_VALUE(#data, '$.Employees[3].Department') AS 'Department',
JSON_VALUE(#data, '$.Employees[3].Address') AS 'Address',
JSON_VALUE(#data, '$.Employees[3].Salary') AS 'Salary'
UNION ALL
SELECT JSON_VALUE(#data, '$.Employees[N].EmpName') AS 'Name',
JSON_VALUE(#data, '$.Employees[N].Department') AS 'Department',
JSON_VALUE(#data, '$.Employees[N].Address') AS 'Address',
JSON_VALUE(#data, '$.Employees[N].Salary') AS 'Salary'

You could use OPENJSON and specify the schema using WITH something like this. The 'EmpName' column is read in from the JSON and renamed to 'Name'
select *
from openjson(#data, N'$.Employees')
with (Name nvarchar(200) N'strict $.EmpName',
Department nvarchar(20),
[Address] nvarchar(20),
Salary nvarchar(20));
Name Department Address Salary
Rohan Sharma IT 101, Sector 5, Gurug 100000
Manohar Lal Human Resources 17, Park Avenue, Mum 78000
Emp 03 Demo Address03 9999
Emp 04 Demo Address04 9999
Emp N Demo AddressN 9999

If you have JSON text's that stored in database table you can read or modify JSON values by using built in functions like
ISJSON (Transact-SQL) tests whether a string contains valid JSON.
JSON_VALUE (Transact-SQL) extracts a scalar value from a JSON string.
JSON_QUERY (Transact-SQL) extracts an object or an array from a JSON
string.
JSON_MODIFY (Transact-SQL) changes a value in a JSON string.
Below example will extract Empname and Department from JSonCol (column with JSON Value)
SELECT JSON_VALUE(jsonCol, '$.Employee.EmpName') AS Empname,
JSON_VALUE(jsonCol, '$.Employee.Deapartment') As Department
FROM Table_Name
Where ISJSON(JsonCol)>0;

Related

Find and Replace Value with id from one Array with another nested Array Object in TypeScript

I have an first array like this
[
["Maths", "Chemistry", "Physics"],
["CS", "EC"],
["High", "Medium", "Low", "Average", "Excellent"]
]
And I have an another array of object in the below format
[
[{
id: 1,
name: "Maths",
is_active: 1
},
{
id: 2,
name: "Chemistry",
is_active: 1
},
{
id: 3,
name: "Physics",
is_active: 1
},
{
id: 4,
name: "Social Science",
is_active: 1
}
],
[{
id: 10,
name: "CS",
is_active: 1
},
{
id: 11,
name: "EC",
is_active: 1
},
{
id: 12,
name: "PHY",
is_active: 1
},
],
[{
id: 101,
name: "High",
is_active: 1
},
{
id: 102,
name: "Low",
is_active: 1
},
{
id: 103,
name: "Medium",
is_active: 1
},
{
id: 104,
name: "Excellent",
is_active: 1
},
{
id: 105,
name: "Average",
is_active: 1
},
{
id: 106,
name: "Below Average",
is_active: 1
},
]
]
I need to replace the first array values with id by matching the names present in first array with name present in the nested array of objects in second array.
My Final Output need to be in this format
[
[1,2,3],
[10,11],
[101,103,102,105,104]
]
Can Anyone help me how to do this in TypeScript.
I can suggest using map() and find() this :
simpleData is your table containing only the names
fullData is your table containing your objects
let fullData = [
[{
id: 1,
name: "Maths",
is_active: 1
},
{
id: 2,
name: "Chemistry",
is_active: 1
},
{
id: 3,
name: "Physics",
is_active: 1
},
{
id: 4,
name: "Social Science",
is_active: 1
}
],
[{
id: 10,
name: "CS",
is_active: 1
},
{
id: 11,
name: "EC",
is_active: 1
},
{
id: 12,
name: "PHY",
is_active: 1
},
],
[{
id: 101,
name: "High",
is_active: 1
},
{
id: 102,
name: "Low",
is_active: 1
},
{
id: 103,
name: "Medium",
is_active: 1
},
{
id: 104,
name: "Excellent",
is_active: 1
},
{
id: 105,
name: "Average",
is_active: 1
},
{
id: 106,
name: "Below Average",
is_active: 1
},
]
]
let simpleData = [
["Maths", "Chemistry", "Physics"],
["CS", "EC"],
["High", "Medium", "Low", "Average", "Excellent"]
]
let newIdTable = [];
for ( let i = 0; i < fullData.length; i++ ) {
let table = simpleData[i].map( ( name ) => {
return fullData[i].find( item => item.name === name ).id
} );
newIdTable.push( table );
}
console.log(newIdTable)
Using find(), if the corresponding object doesn't exist it will return undefined. I didn't test the case here, because I supposed that your object already exist in the fullData table. So you have to modify the code with a condition to handle that case if you need :)

Units for specifying width (of a table column) in Antd?

We are using the latest stable version 2 of Antd (and cannot make the jump to version 3 due to version dependency constraints). How do we specify the width of my table columns, ideally to the length of the text in title property? According to the official table component docu, there is the obvious property width for a column. All the documentation says in English is
Property: width
Description: Width of this column
Type: string|number
Default: -
1st part of the question: If I specify only a number, what unit is used? I tried different things, but it does not really look like it is dp as described e.g at What is the default unit for width, height, padding etc in React Native for iOS?
2nd part: If I specify a string, which units can I use? I tried ex, em, and px and none of them seems to work.
The 3rd part of the question: Maybe we overlooked a property of the table tag which overwrites or limits the usage of width is a column?
Any input is appreciated, already the translation of the original documentation to English would help. Or explaining the a related Github issue: 'how to set table columns width? the width property is invalid'.
Thanks for your time in advance - a puzzled Antd newbie.
From the antd official document:
import { Table } from 'antd';
const columns = [{
title: 'Name',
dataIndex: 'name',
key: 'name',
width: '40%',
}, {
title: 'Age',
dataIndex: 'age',
key: 'age',
width: '30%',
}, {
title: 'Address',
dataIndex: 'address',
key: 'address',
}];
const data = [{
key: 1,
name: 'John Brown sr.',
age: 60,
address: 'New York No. 1 Lake Park',
children: [{
key: 11,
name: 'John Brown',
age: 42,
address: 'New York No. 2 Lake Park',
}, {
key: 12,
name: 'John Brown jr.',
age: 30,
address: 'New York No. 3 Lake Park',
children: [{
key: 121,
name: 'Jimmy Brown',
age: 16,
address: 'New York No. 3 Lake Park',
}],
}, {
key: 13,
name: 'Jim Green sr.',
age: 72,
address: 'London No. 1 Lake Park',
children: [{
key: 131,
name: 'Jim Green',
age: 42,
address: 'London No. 2 Lake Park',
children: [{
key: 1311,
name: 'Jim Green jr.',
age: 25,
address: 'London No. 3 Lake Park',
}, {
key: 1312,
name: 'Jimmy Green sr.',
age: 18,
address: 'London No. 4 Lake Park',
}],
}],
}],
}, {
key: 2,
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
}];
// rowSelection objects indicates the need for row selection
const rowSelection = {
onChange: (selectedRowKeys, selectedRows) => {
console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
},
onSelect: (record, selected, selectedRows) => {
console.log(record, selected, selectedRows);
},
onSelectAll: (selected, selectedRows, changeRows) => {
console.log(selected, selectedRows, changeRows);
},
};
ReactDOM.render(
<Table columns={columns} rowSelection={rowSelection} dataSource={data} />
, mountNode);

Grouping objects with lodash or ES5

I'm a javascript noobie, I started to use the library lodash and I'm having some problems. Can someone help me? :/
Input:
var a = [{group: 'A', title: 'test1', value: 'test2'},
{group: 'A', title: 'test2', value: 'test3'},
{group: 'B', title: 'test3', value: 'test4'},
{group: 'B', title: 'test1', value: 'test2'},]
Output:
var a = {A: [
{ title: 'test1', value: 'test2'},
{ title: 'test2', value: 'test3'}
],
B: [
{ title: 'test1', value: 'test2'},
{ title: 'test2', value: 'test3'}
],}
You can group with _.groupBy() and then use _.mapValues() on each group to remove the group property from the objects by mapping them to a new object using _.omit().
const a = [{group: 'A', title: 'test1', value: 'test2'},
{group: 'A', title: 'test2', value: 'test3'},
{group: 'B', title: 'test3', value: 'test4'},
{group: 'B', title: 'test1', value: 'test2'}
];
const result = _(a)
.groupBy('group') // group by the group prop
.mapValues((group) => group.map((o) => _.omit(o, 'group'))) // remove the group prop from each item
.value();
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
The lodash documentation for group by is pretty explicit you can find it here.
In your case it would look something like this.
_.groupBy(a, 'group')
You can also do it yourself pretty easily as well using the reduce function. It would look something like this:
let groups = a.reduce((grouping, currentItem) => {
if (!grouping[currentItem.group]) {
grouping[currentItem.group] = []
}
grouping[currentItem.group].push(currentItem);
return grouping;
}, {});
A working example can be found here.
In both cases the result would be an object with the groups as property names.
{
"A": [{
"group": "A",
"title": "test1",
"value": "test2"
}, {
"group": "A",
"title": "test2",
"value": "test3"
}],
"B": [{
"group": "B",
"title": "test3",
"value": "test4"
}, {
"group": "B",
"title": "test1",
"value": "test2"
}]
}

header row template in ng-grid

I have created an ng-grid and want to customise Header Row Template of the grid as i need to add total items in header instead of the footer, but want the same view as footer (i mean the whole row ). I already know about headerCellTemplate and also have already tried it but its not what i am looking for ! if you can help i will be so thankful to you :)
here is sample of my code
$scope.myData = [{"name": "Moroni", "age": 50},
{"name": "Tiancum", "age": 53},
{"name": "Jacob", "age": 27},
{"name": "Nephi", "age": 54},
{"name": "Alex", "age": 53},
{"name": "Jhonny", "age": 22},
{"name": "Ben", "age": 11},
],
$scope.gridOptions = {
data: 'myData',
columnDefs: [
{ field: 'name', displayName: 'Candiate name' },
{ field: 'age', displayName: 'Age', headerCellTemplate: myHeaderCellTemplate }
]
};
You don't need to do that as part of the grid. Just add a div above the grid and put whatever you want in it. You can use the same styles as the footer does to make it match.

extjs parsing nested json in template

Trying (unsuccessfully) to display data from nested json.
JSON might look something like:
{
"contacts": [
{
"id": "1",
"client_id": "135468714603",
"addresses": [
{
"id": "1",
"contact_id": "1",
"address_id": "16",
"address": {
"0": {
"id": "16",
"address": "123 Some Rd",
"address2": "",
"city": "Toen",
"state": "VS",
"zip_code": "11111",
"country": "USA"
}
}
},
{
"id": "6",
"contact_id": "1",
"address_id": "26",
"address": {
"0": {
"id": "26",
"address": "1 Other Road",
"address2": "",
"city": "Twn",
"state": "BD",
"zip_code": "11112",
"country": "USA"
}
}
}
]
},
{
"id": "10",
"client_id": null,
"addresses": [
{
"id": "8",
"contact_id": "10",
"address_id": "28",
"address": {
"0": {
"id": "28",
"address": "54 Road",
"address2": "",
"city": "TWND",
"state": "TT",
"zip_code": "11113",
"country": "USA"
}
}
},
{
"id": "9",
"contact_id": "10",
"address_id": "29",
"is_mailing_address": "0",
"is_primary_address": "0",
"display_priority": "0",
"address": {
"0": {
"id": "29",
"address": "6 Road",
"address2": "",
"city": "TOEOEOWN",
"state": "PY",
"zip_code": "11116",
"country": "USA"
}
}
},
{
"id": "10",
"contact_id": "10",
"address_id": "30",
"address": {
"0": {
"id": "30",
"address": "PO Box 9",
"address2": "",
"city": "TOYN",
"state": "GF",
"zip_code": "11118",
"country": "USA"
}
}
}
]
},
{
"id": "11",
"client_id": null,
"contact_id": "11",
"addresses": [
{
"id": "11",
"contact_id": "11",
"address_id": "33",
"is_mailing_address": "0",
"is_primary_address": "0",
"display_priority": "0",
"address": {
"0": {
"id": "33",
"address": "4 Street",
"address2": "",
"city": "TEOIN",
"state": "TG",
"zip_code": "11119",
"country": "USA"
}
}
}
]
}
]
}
I've tried mapping model fields to what I need (e.g. contacts model > addresses field > mapping: addresses), but this doesn't work because I'd need to map to addresses[0].address[0] to get the data which obviously discards the other addresses.
I've also tried playing around with associations, but this appears to be separate models and stores. The idea here is to not make a separate request for the contacts and then their addresses.
I've also tried digging into the json straight in the template (which seemed to be the most straightforward way) e.g. {addresses.address.city} which doesn't work.
The thinking is simple: grab some json, and display different parts of said json in different parts of the app.
The experience has been dreadful.
Can someone explain how to map these nested json items so that they are accessible from a template?
Template:
{
xtype: 'container',
flex: 1,
id: 'mainPanel',
items: [
{
xtype: 'dataview',
hidden: false,
id: 'clientsContacts',
minHeight: 200,
itemSelector: 'div',
itemTpl: [
'{id} | {last_name} | {first_name} | {relationship} | {addresses}'
],
store: 'Contacts'
}
]
}
Store:
Ext.define('MyApp.store.Contacts', {
extend: 'Ext.data.Store',
requires: [
'MyApp.model.Contacts'
],
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
autoLoad: false,
storeId: 'Contacts',
model: 'MyApp.model.Contacts',
proxy: {
type: 'ajax',
extraParams: {
id: '',
format: 'json'
},
url: '/api/contacts/', //the json
reader: {
type: 'json',
root: 'contacts'
}
},
listeners: {
load: {
//fn: me.onJsonstoreLoad,
//scope: me
}
}
}, cfg)]);
},
});
Model:
Ext.define('MyApp.model.Contacts', {
extend: 'Ext.data.Model',
uses: [
//'MyApp.model.Client',
//'MyApp.model.contactAddressModel'
],
fields: [
{
name: 'client_id'
},
{
name: 'id'
},
{
name: 'addresses',
mapping: 'addresses'//doesn't work
//mapping: 'addresses[0].address[0]' //works, but only for the first address duh
}
],
});
Using extjs 4.1 via Sencha Architect.
Any help would be greatly appreciated.
Thanks.
I think I got it (hopefully it's correct).
So, create a field for each nested group of data you need. So I have a Contacts model. In that model there are these fields:
id
client_id
addresses //mapped to addresses
address //mapped to addresses.address
then in the template:
<br>
<tpl for="addresses">
id: {id}<br>
addy id: {address_id}<br>
<tpl for="address">
{city} {state}, {zip}<br>
</tpl>
</tpl>
This is what the whole thing looks like:
View
Ext.define('MyApp.view.MyView', {
extend: 'Ext.view.View',
height: 250,
width: 400,
itemSelector: 'div',
store: 'MyJsonStore',
initComponent: function() {
var me = this;
Ext.applyIf(me, {
itemTpl: [
'<br>',
'<tpl for="addresses">',
' id: {id}<br>',
' addy id: {address_id}<br>',
' <b>',
' <tpl for="address">',
' {city} {state}, {zip}<br><br>',
' </tpl>',
' </b>',
'',
'</tpl>',
'',
'<hr>',
''
]
});
me.callParent(arguments);
}
});
Store
Ext.define('MyApp.store.MyJsonStore', {
extend: 'Ext.data.Store',
requires: [
'MyApp.model.Contacts'
],
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
storeId: 'MyJsonStore',
model: 'MyApp.model.Contacts',
data: {
contacts: [
{
id: '1',
client_id: '135468714603',
addresses: [
{
id: '1',
contact_id: '1',
address_id: '16',
address: {
'0': {
id: '16',
address: '123 Some Rd',
address2: '',
city: 'Toen',
state: 'VS',
zip_code: '11111',
country: 'USA'
}
}
},
{
id: '6',
contact_id: '1',
address_id: '26',
address: {
id: '26',
address: '1 Other Road',
address2: '',
city: 'Twn',
state: 'BD',
zip_code: '11112',
country: 'USA'
}
}
]
},
{
id: '10',
client_id: null,
addresses: [
{
id: '8',
contact_id: '10',
address_id: '28',
address: {
id: '28',
address: '54 Road',
address2: '',
city: 'TWND',
state: 'TT',
zip_code: '11113',
country: 'USA'
}
},
{
id: '9',
contact_id: '10',
address_id: '29',
is_mailing_address: '0',
is_primary_address: '0',
display_priority: '0',
address: {
id: '29',
address: '6 Road',
address2: '',
city: 'TOEOEOWN',
state: 'PY',
zip_code: '11116',
country: 'USA'
}
},
{
id: '10',
contact_id: '10',
address_id: '30',
address: {
id: '30',
address: 'PO Box 9',
address2: '',
city: 'TOYN',
state: 'GF',
zip_code: '11118',
country: 'USA'
}
}
]
},
{
id: '11',
client_id: null,
contact_id: '11',
addresses: [
{
id: '11',
contact_id: '11',
address_id: '33',
is_mailing_address: '0',
is_primary_address: '0',
display_priority: '0',
address: {
id: '33',
address: '4 Street',
address2: '',
city: 'TEOIN',
state: 'TG',
zip_code: '11119',
country: 'USA'
}
}
]
}
]
},
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'contacts'
}
}
}, cfg)]);
}
});
Model
Ext.define('MyApp.model.Contacts', {
extend: 'Ext.data.Model',
fields: [
{
name: 'id'
},
{
name: 'client_id'
},
{
name: 'addresses',
mapping: 'addresses'
},
{
name: 'address',
mapping: 'address'
}
]
});
I have verified that the above answer does work, but to note for future people, that if you don't specify the name of sub fields, you don't need the 2nd nested template. You can do it with just the first.

Resources