Run into issue with parsing fairly complex JSON data.
What I am trying to achieve is parse the json data, extract address information and populate that in the typeahead drop down list.
JSON Data:
"{
"Version":"2.0.20",
"ResultCode":"XS02",
"ErrorString":"",
"Results":
[
{"Address":
{"AddressLine1":"300 1/2 E Manor Ave","City":"Anchorage","CityAccepted":"","CityNotAccepted":"","State":"AK","PostalCode":"99501","CountrySubdivisionCode ":"US-AK","AddressKey":"99501118273","SuiteName":"Apt","SuiteCount":3,"SuiteList":["","Apt A","Apt B"],"PlusFour":["1182","1182","1182"]}
},
{"Address":
{"AddressLine1":"240 1/2 E Manor Ave","City":"Anchorage","CityAccepted":"","CityNotAccepted":"","State":"AK","PostalCode":"99501-1150","CountrySubdivisionCode ":"US-AK","AddressKey":"99501115040","SuiteName":"","SuiteCount":0,"SuiteList":[""],"PlusFour":[""]}
},
{"Address":
{"AddressLine1":"308 1/2 E Manor Ave","City":"Anchorage","CityAccepted":"","CityNotAccepted":"","State":"AK","PostalCode":"99501-1152","CountrySubdivisionCode ":"US-AK","AddressKey":"99501115208","SuiteName":"","SuiteCount":0,"SuiteList":[""],"PlusFour":[""]}
},
{"Address":{"AddressLine1":"301 1/2 E Manor Ave","City":"Anchorage","CityAccepted":"","CityNotAccepted":"","State":"AK","PostalCode":"99501-1151","CountrySubdivisionCode ":"US-AK","AddressKey":"99501115101","SuiteName":"","SuiteCount":0,"SuiteList":[""],"PlusFour":[""]}
},
]
}"
I only need to parse all the Addresses and extract AddressLine1 + City + State + PostalCode
JQuery:
$('#taquery').typeahead({
hint: true,
highlight: true,
minLength: 3
},
{
name: 'states',
displayKey: 'value',
source: function (query, process) {
return $.ajax({
url: "/addressLookup",
type: 'get',
data: { query: query },
dataType: 'json',
success: function (data) {
return typeof data == 'undefined' ? false : processResult(data);
}
});
}
});
var processResult = function (data) {
var addArray = $.makeArray(data.Results);
$.map(addArray, function (item, i) {
return (formatAddressJson(item.Address, i));
});
};
var formatAddressJson = function (addr, idx) {
var rtn;
rtn = {
fullAddress: addr.AddressLine1 + ', ' + addr.City + ', ' + addr.State + ', ' + addr.PostalCode,
addrLine1: addr.AddressLine1,
city: addr.City,
state: addr.State,
zip: addr.PostalCode.substring(0, 5),
idx: idx
};
return rtn;
}
Error:
jquery-1.10.2.min.js:4 Uncaught TypeError: Cannot use 'in' operator to search for '2548' in {"Version":"2.0.20","ResultCode":"XS02","ErrorString":"","Results":[{"Address":{"AddressLine1":"300 1/2 E Manor
var data = JSON.parse(response);
var addresses = data.results.reduce(function(agg, cur, idx) {
agg.push(formatAddress(cur.Address, idx)
return agg;
}, []);
function formatAddress(adr, idx) { //...your method }
// now you can loop over addresses array and access each.
addresses.forEach(function(addressObject) { console.log(addressObject) });
this code should make it work, you should use reduce method instead of map, and you do not need jquery to accomplish this.
EDIT
var JSON_FROM_SUCCESS_FUNCTION = {
"Version": "2.0.20",
"ResultCode": "XS02",
"ErrorString": "",
"Results": [{
"Address": { "AddressLine1": "300 1/2 E Manor Ave", "City": "Anchorage", "CityAccepted": "", "CityNotAccepted": "", "State": "AK", "PostalCode": "99501", "CountrySubdivisionCode ": "US-AK", "AddressKey": "99501118273", "SuiteName": "Apt", "SuiteCount": 3, "SuiteList": ["", "Apt A", "Apt B"], "PlusFour": ["1182", "1182", "1182"] }
}, {
"Address": { "AddressLine1": "240 1/2 E Manor Ave", "City": "Anchorage", "CityAccepted": "", "CityNotAccepted": "", "State": "AK", "PostalCode": "99501-1150", "CountrySubdivisionCode ": "US-AK", "AddressKey": "99501115040", "SuiteName": "", "SuiteCount": 0, "SuiteList": [""], "PlusFour": [""] }
}, {
"Address": { "AddressLine1": "308 1/2 E Manor Ave", "City": "Anchorage", "CityAccepted": "", "CityNotAccepted": "", "State": "AK", "PostalCode": "99501-1152", "CountrySubdivisionCode ": "US-AK", "AddressKey": "99501115208", "SuiteName": "", "SuiteCount": 0, "SuiteList": [""], "PlusFour": [""] }
}, {
"Address": { "AddressLine1": "301 1/2 E Manor Ave", "City": "Anchorage", "CityAccepted": "", "CityNotAccepted": "", "State": "AK", "PostalCode": "99501-1151", "CountrySubdivisionCode ": "US-AK", "AddressKey": "99501115101", "SuiteName": "", "SuiteCount": 0, "SuiteList": [""], "PlusFour": [""] }
}]
};
/*
$('#taquery').typeahead({
hint: true,
highlight: true,
minLength: 3
}, {
name: 'states',
displayKey: 'value',
source: function (query, process) {
return $.ajax({
url: "/addressLookup",
type: 'get',
data: { query: query },
dataType: 'json',
success: function (data) {
return typeof data == 'undefined' ? false : processResult(data);
}
});
}
});
*/
function processResult(data) {
return data.Results.reduce(function(agg, cur, idx) {
agg.push(formatAddress(cur.Address, idx));
return agg;
}, []);
};
function formatAddress(addr, idx) {
var fullAddress = addr.AddressLine1 + ', ' + addr.City + ', ' + addr.State + ', ' + addr.PostalCode;
return {
fullAddress: fullAddress,
addrLine1: addr.AddressLine1,
city: addr.City,
state: addr.State,
zip: addr.PostalCode.substring(0, 5),
idx: idx
};
}
var addresses = processResult(JSON_FROM_SUCCESS_FUNCTION);
// now you can loop over addresses array and access each.
addresses.forEach(function(addressObject) { console.log(addressObject) });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Related
I have this JSON generated from external (Reviews-io) script:
https://widget.reviews.co.uk/rich-snippet/dist.js
richSnippet({
store: "www.storedigital.local",
sku:"6647;6647_5;6647_4;6647_3;6647_11;6647_10;6647_2;6647_1;6647_9;6647_8;6647_7;6647_6",
data:{
"url": "store.stg.gsd.local/1/silla-replica-eames.html",
"description": ``,
"mpn": "6647",
"offers" :[{
"#type":"Offer",
"availability": "http://schema.org/InStock",
"price": "559",
"priceCurrency": "MXN",
"url": "https://store.stg.gsd.localx/1/silla-replica-eames.html",
"priceValidUntil": "2022-05-26",
}],
"brand": {
"#type": "Brand",
"name": "Not Available",
}
}
})
I need to get all the string of numbers in "sku", and then put them in another variable as same format (6647; 6647_1; 6647_2)
I try to get the numbers using this JS but doesn't works
var skucollection = JSON.parse(richSnippet, function (key, value) {
if (key == "sku") {
return new Sku(value);
} else {
return value;
}
});
Can you help me check what I am doing wrong, to get this sku's value string, please?
JSON.parse is not too much? ,handle it as it is internally (a JSON indeed)
var richSnippet = {
store: 'www.storedigital.local',
sku: '6647;6647_5;6647_4;6647_3;6647_11;6647_10;6647_2;6647_1;6647_9;6647_8;6647_7;6647_6',
algomas: [],
data: {
url: 'store.stg.gsd.local/1/silla-replica-eames.html',
description: ``,
mpn: '6647',
offers: [
{
'#type': 'Offer',
availability: 'http://schema.org/InStock',
price: '559',
priceCurrency: 'MXN',
url: 'https://store.stg.gsd.localx/1/silla-replica-eames.html',
priceValidUntil: '2022-05-26',
},
],
brand: {
'#type': 'Brand',
name: 'Not Available',
},
},
};
var test;
Object.keys(richSnippet).forEach((key) => {
if (key == 'sku') {
test = richSnippet[key];
}
});
console.log('test', test);
I have a JSON tree likes this Github link
As you can see, this tree uses formula property on each item to calculate its value. So I need to calculate the value of a few nodes or root nodes.
You can see PL6A, PL6B is the end of tree with type = 1. So I need to replace up to the tree so which formula construct by PLVALUE must be replaced with ACVALUE.
Example:
PL10 formula must be replace with (ACVALUE(PL6A)+ACVALUE(PL6B))+...
How can I do that, thank you and sorry for bad English
Update
I have tried this code:
for (let i = 0; i < accounts.length; i++) {
const item = accounts[i];
let { formula } = accounts[i];
if (item.children.length && item.type === 2) {
//Replace formula with full children formula
item.children.forEach((child) => {
if (formula.indexOf(child.code) > -1) {
const fullInfoChild = accounts.find(
(fullInfoItem) => _.trim(fullInfoItem._id) === _.trim(child._id)
);
formula = _.replace(
formula,
`PLVALUE(${child.code})`,
`(${fullInfoChild.formula})`
);
}
});
} else {
formula = item.formula;
}
accounts[i].formula = formula;
}
and the result, some node work well
{
"_id": "5cf6159f386f5942aabca347",
"code": "PL10",
"formula": "(ACVALUE(PL6A)+ACVALUE(PL6B))+(ACVALUE(PL9))+(ACVALUE(PL7B)+ACVALUE(PL7A))+(ACVALUE(PL8A)+ACVALUE(PL8B))+(ACVALUE(DSRGP))",
"status": 1,
"type": 2,
"parents": [
{
"_id": "5cf61756386f5942aabca365",
"code": "PL28",
"formula": "PLVALUE(PL10)+PLVALUE(PL15)",
"status": 1,
"type": 2
}
],
"children": [
{
"_id": "5cf614f4386f5942aabca342",
"code": "PL6",
"formula": "ACVALUE(PL6A)+ACVALUE(PL6B)",
"status": 1,
"type": 2
},
{
"_id": "5cf6156a386f5942aabca346",
"code": "PL_DSRGP",
"formula": "ACVALUE(DSRGP)",
"status": 1,
"type": 2
},
{
"_id": "5cf6152f386f5942aabca345",
"code": "PL9",
"formula": "ACVALUE(PL9)",
"status": 1,
"type": 2
},
{
"_id": "5cf6150e386f5942aabca343",
"code": "PL7",
"formula": "ACVALUE(PL7B)+ACVALUE(PL7A)",
"status": 1,
"type": 2
},
{
"_id": "5cf6151e386f5942aabca344",
"code": "PL8",
"formula": "ACVALUE(PL8A)+ACVALUE(PL8B)",
"status": 1,
"type": 2
}
],
"totalCurrentYear": 0
},
but if we up some level it not work like this one
{
"_id": "5cf8c78b4aafe73cb56ce424",
"code": "PL30",
"formula": "(((ACVALUE(PL6A)+ACVALUE(PL6B))+(ACVALUE(PL9))+(ACVALUE(PL7B)+ACVALUE(PL7A))+(ACVALUE(PL8A)+ACVALUE(PL8B))+(ACVALUE(DSRGP)))+((ACVALUE(511000)+ACVALUE(735013)+ACVALUE(511100))+(ACVALUE(511002)+ACVALUE(511101)+ACVALUE(554020)+ACVALUE(735015))+(ACVALUE(511003)+ACVALUE(511102)+ACVALUE(735016))+(ACVALUE(511004)+ACVALUE(554010)+ACVALUE(554021)+ACVALUE(735017)+ACVALUE(554030))))+(PLVALUE(PL23)+PLVALUE(PL24)+PLVALUE(PL25))",
"status": 1,
"type": 2,
"children": [
{
"_id": "5cf61756386f5942aabca365",
"code": "PL28",
"formula": "PLVALUE(PL10)+PLVALUE(PL15)",
"status": 1,
"type": 2
},
{
"_id": "5cf8c7bd4aafe73cb56ce426",
"code": "PL26",
"formula": "PLVALUE(PL23)+PLVALUE(PL24)+PLVALUE(PL25)",
"status": 1,
"type": 2
}
],
},
Updated: Add full json data to github link
You could collect the references to the code/formula and the formulas to replace and iterate the formulas to get the values.
var data = [{ _id: "5cf8c78b4aafe73cb56ce424", code: "PL30", formula: "PLVALUE(PL28)+PLVALUE(PL26)", status: 1, type: 2, children: [{ _id: "5cf61756386f5942aabca365", code: "PL28", formula: "PLVALUE(PL10)+PLVALUE(PL15)", status: 1, type: 2 }, { _id: "5cf8c7bd4aafe73cb56ce426", code: "PL26", formula: "PLVALUE(PL23)+PLVALUE(PL24)+PLVALUE(PL25)", status: 1, type: 2 }] }, { _id: "5cf61756386f5942aabca365", code: "PL28", formula: "PLVALUE(PL10)+PLVALUE(PL15)", status: 1, type: 2, children: [{ _id: "5cf6159f386f5942aabca347", code: "PL10", formula: "PLVALUE(PL6)+PLVALUE(PL9)+PLVALUE(PL7)+PLVALUE(PL8)+PLVALUE(PL_DSRGP)", status: 1, type: 2 }, { _id: "5cf61741386f5942aabca364", code: "PL15", formula: "PLVALUE(PL11)+PLVALUE(PL12)+PLVALUE(PL13)+PLVALUE(PL14)", status: 1, type: 2 }], totalCurrentYear: 0 }, { _id: "5cf6159f386f5942aabca347", code: "PL10", formula: "PLVALUE(PL6)+PLVALUE(PL9)+PLVALUE(PL7)+PLVALUE(PL8)+PLVALUE(PL_DSRGP)", status: 1, type: 2, children: [{ _id: "5cf614f4386f5942aabca342", code: "PL6", formula: "ACVALUE(PL6A)+ACVALUE(PL6B)", status: 1, type: 2 }, { _id: "5cf6156a386f5942aabca346", code: "PL_DSRGP", formula: "ACVALUE(DSRGP)", status: 1, type: 2 }, { _id: "5cf6152f386f5942aabca345", code: "PL9", formula: "ACVALUE(PL9)", status: 1, type: 2 }, { _id: "5cf6150e386f5942aabca343", code: "PL7", formula: "ACVALUE(PL7B)+ACVALUE(PL7A)", status: 1, type: 2 }, { _id: "5cf6151e386f5942aabca344", code: "PL8", formula: "ACVALUE(PL8A)+ACVALUE(PL8B)", status: 1, type: 2 }] }, { _id: "5cf614f4386f5942aabca342", code: "PL6", formula: "ACVALUE(PL6A)+ACVALUE(PL6B)", status: 1, type: 2, children: [{ _id: "5cf61869386f5942aabca368", code: "PL6A", type: 1, status: 1 }, { _id: "5cf6187f386f5942aabca36a", code: "PL6B", type: 1, status: 1 }], totalCurrentYear: 0 }],
replace = (formula, values) => formula.replace(/PLVALUE\(([^\)]+)\)/g, (full, group) => group in values
? `(${values[group].object[values[group].key]})`
: full
),
getNestedValues = (r, object) => {
r.values[object.code] = { object, key: object.type === 1 ? 'code' : 'formula' };
if (object.formula?.includes('PLVALUE')) r.formulas.push(object);
if (object.children) object.children.reduce(getNestedValues, r);
return r;
},
{ values, formulas } = data.reduce(getNestedValues, { values: {}, formulas: [] });
// while (formulas.length) { // only if all targets are known
let i = formulas.length;
while (i--) {
let s = replace(formulas[i].formula, values);
if (s === formulas[i].formula) continue;
formulas[i].formula = s;
formulas.splice(i, 1);
}
// } // only if all targets are known
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I have this jSON structure.
{
"customer": {
"idcustomer": 2,
"name": "test_2",
"vat": "test_vat_2",
"obs": "obs_2",
"deleted": 0
},
"addresses": [
{
"idaddress": 9,
"street": "street_2_9",
"number": "number_2_9",
"country": "country_2_9",
"default": true,
"label": "labe_2_9",
"deleted": 0
},
{
"idaddress": 10,
"street": "1",
"number": "number_2_9",
"country": "country_2_10",
"default": false,
"label": "label_2_10",
"deleted": 0
}
],
"contacts": []
}
With knockout mapping plugin I am able to generate a knockout observable object. However, when trying to add extra properties to the object using the mapping parameter I find some issues. The goal is to add "SelectedAddress" to the main object and in each address a "defaultLabel" observabale.
Currently i have this mapping structure to add the property to the address children:
var mapping = {
'addresses': {
create: function (options) {
return (new (function () {
this.defaultLabel= ko.computed(function () {
return (this.default() == 0) ? "" : this.label();
}, this);
ko.mapping.fromJS(options.data, {}, this);
})());
}
},
}
and this to add the "SelectedAddress" to the main JSON:
create: function (options) {
return new function () {
var model = ko.mapping.fromJS(options.data, {}, this);
// Direccion
model.direccionSeleccionada = ko.observable();
model.getDireccion = ko.computed({
read: function() {
if (model.direccionSeleccionada() != null) {
return model.direccionSeleccionada();
} else {
return [{
idaddress: -1,
street : '',
number: '',
country: '',
default: '',
label: '',
deleted: '',
}];
}
},
write: function(value) {
self.direccionSeleccionada(value);
},
owner: self
});
}
}
I can not find a way to have them both
Ideas?
Thank you
I figured it out. Just for someone; Just as simple as when generatint he mapping of "addresses", add inside another mapping for it.
var mapping = {
create: function (options) {
return new function () {
var model = ko.mapping.fromJS(options.data, {
'adresses': {
create: function (options) {
return (new(function () {
this.labelDefault= ko.computed(function () {
return (this.default() == 0) ? "" : this.label();
}, this);
ko.mapping.fromJS(options.data, {}, this);
})( /* call the ctor here */ ));
}
},
}, this);
model.direccionSeleccionada = ko.observable();
model.getDireccion = ko.computed({
read: function () {
if (model.selectedAddress() != null) {
return model.selectedAddress();
} else {
return [{
idaddress: -1,
street: '',
number: '',
country: '',
default: '',
label: '',
deleted: ''
}];
}
},
write: function (value) {
self.selectedAddress(value);
},
owner: self
});
}
}
}
Thank you!
I'm trying to use the data in my API to populate a select input. I'm using Select2 and have everything working but am unable to select anything once results are found. I'll post my code below, I've been working on this for over 12 hours and can't find anything on the internet that works or even helps to get closer.
HTML:
<select id="school_input"></select>
Select2 Setup:
function formatResults (results) {
if (results.loading) return "Searching...";
var markup = "<div class='select2-result'>" + results.school_name + "</div>";
return markup;
}
$('#school_input').select2({
ajax: {
url: "http://services.url.com/services/globalopponentlookup.ashx",
dataType: 'jsonp',
delay: 250,
data: function (params) {
return {
school_name: params.term,
};
},
processResults: function (data, params) {
return {
results: data.schools,
};
},
cache: true
},
escapeMarkup: function (markup) { return markup; },
minimumInputLength: 3,
templateResult: formatResults
});
Example of data being pulled in from API:
jQuery31101273177236076506_1487863085363({
"schools": [
{
"school_search_keywords": "florida",
"website": "http://www.cf.edu/",
"school_id": "1514",
"school_name": "Central Florida Community College",
"school_website": "http://www.cf.edu/",
"school_location": "Ocala, FL ",
"school_mascot": "Patriots",
"school_logo_file": "CFpats.png",
"conference_id": "155",
"school_last_updated": "2/26/2014 9:23:51 AM",
"school_zip": "34474",
"school_ncaa_code": "0",
"school_abbrev": null,
"logo": "http://clients.url.com/files/logos/njcaa/CFpats.png",
"colors_id": null,
"url": null,
"safe_text_white": null,
"safe_text_black": null,
"primary_background": null,
"primary_text": null,
"secondary_background": null,
"secondary_text": null,
"client_id": null,
"created": null,
"deleted": null
},
{
"school_search_keywords": "florida",
"website": "http://www.easternflorida.edu/athletics/",
"school_id": "2521",
"school_name": "Eastern Florida State College",
"school_website": "http://www.easternflorida.edu/athletics/",
"school_location": "Cocoa, FL",
"school_mascot": "Titans",
"school_logo_file": "Eastern-Florida-State.png",
"conference_id": "155",
"school_last_updated": "1/19/2016 4:03:58 PM",
"school_zip": "32922",
"school_ncaa_code": null,
"school_abbrev": "EFSC",
"logo": "http://clients.url.com/files/logos/njcaa/Eastern-Florida-State.png",
"colors_id": null,
"url": null,
"safe_text_white": null,
"safe_text_black": null,
"primary_background": null,
"primary_text": null,
"secondary_background": null,
"secondary_text": null,
"client_id": null,
"created": null,
"deleted": null
}
]
You need to have Id value in the JSON in order to make it selectable. https://jsfiddle.net/adiioo7/Lqso63mw/2/
JS
function formatResults (results) {
if (results.loading) return "Searching...";
var markup = "<div class='select2-result'>" + results.school_name + "</div>";
return markup;
}
function formatRepoSelection (results) {
return results.school_name;
}
$('#school_input').select2({
ajax: {
url: "https://api.myjson.com/bins/15d345",
dataType: 'json',
delay: 250,
data: function (params) {
return {
school_name: params.term,
};
},
processResults: function (data, params) {
$(data.schools).each(function(){
this.id=this.school_id;
});
return {
results: data.schools,
};
},
cache: true
},
escapeMarkup: function (markup) { return markup; },
minimumInputLength: 3,
templateResult: formatResults,
templateSelection: formatRepoSelection
});
You need to return your markup from the formatResults() function :
function formatResults (results) {
if (results.loading) return "Searching...";
return "<div class='select2-result'>" + results.school_name + "</div>";
}
See the documentation
I am using Elasticsearch and AngularJS to build a small search application. I'm trying to use Angular UI Bootstrap Typeahead to implement an autocomplete feature using the http.get call for asynchronous results and am not exactly sure where to put it?.... still learning ES and Angular.
Where would I put this http.get call inside this js promise code?
http.get code:
return $http.get('localhost:9200/bigtestindex/doc/_search', {
params: {
"query": {
"match": {
"content.autocomplete": {
"query": query,
"default_operator": "and"
}
}
}
}
}),
Javascript promise code:
this.getSuggestions = function(query) {
var deferred = $q.defer();
var terms = query.split(' '),
baseTerms = terms.length === 1 ? '' : terms.slice(0, -1).join(' ') + ' ',
lastTerm = terms[terms.length - 1].toLowerCase();
esClient.search({
index: 'bigtestindex',
body: {
"query": {
"simple_query_string": {
"fields": ['title'],
"query": baseTerms + '(' + lastTerm + '|' + lastTerm + '*)',
"default_operator": "and"
}
},
"suggest": {
"text": query,
"phraseSuggestion": {
"phrase": {
"field": "title",
"direct_generator": [{
"field": "title",
"suggest_mode": "popular",
"min_word_length": 3,
"prefix_length": 2
}]
}
}
},
"size": 5,
"_source": ["content"]
}
}).then(function(es_return) {
deferred.resolve(es_return);
}, function(error) {
deferred.reject(error);
});
return deferred.promise;
};
I am pretty sure in goes in the body somewhere just not sure where... I can't get it to work.
I suppose, your controller code could look like this:
function searchController(esClient)
{
var ctl = this;
ctl.suggestions = [];
this.getSuggestions = function(query) {
var terms = query.split(' '),
baseTerms = terms.length === 1 ? '' : terms.slice(0, -1).join(' ') + ' ',
lastTerm = terms[terms.length - 1].toLowerCase();
esClient.search({
index: 'bigtestindex',
body: {
"query": {
"simple_query_string": {
"fields": ['title'],
"query": baseTerms + '(' + lastTerm + '|' + lastTerm + '*)',
"default_operator": "and"
}
},
"suggest": {
"text": query,
"phraseSuggestion": {
"phrase": {
"field": "title",
"direct_generator": [{
"field": "title",
"suggest_mode": "popular",
"min_word_length": 3,
"prefix_length": 2
}]
}
}
},
"size": 5,
"_source": ["content"]
}
}, function(err, es_return) {
if(err) {
//Handle error or do nothing
return;
}
ctl.suggestions = es_return;
});
};
}