Convert and parse json string to key value pairs using NewtonSoft - json

Trying to convert a json string to key value pairs using Newtonsoft but no luck so far.
Response from the API:
var response = #"{'result':{'0199 - B344EE33':
{
'6400_00260100':{'1':[{'val':336688}]},
'6400_00462500':{'1':[{'val':null}]},
'6800_00832A00':{'1':[{'low':3000,'high':3000,'val':3000}]},
'6800_008AA200':{'1':[{'low':0,'high':null,'val':0}]}
}}}";
Result I want is a new object of key value pairs:
{
"6400_00260100" : 336688,
"6400_00462500" : null,
"6800_00832A00" : 3000,
"6800_008AA200" : 0
}
In the response the result will always be the first and only prop. In the next level the code 0199 - B344EE33 can change but there will be only one prop in this level so we can always take the first one. Then in the last level we always need the val property.
What I have is the following but for getting the key value pairs in a clean way I got stuck:
var json = JObject.Parse(response);
var result = json["result"].First;
var path = result.Path;
UPDATE
var jObjectResult = new JObject();
var response = #"{'result':{'0199 - B344EE33':
{
'6800_10821E00':{'1':[{'val':'SMA Sunny Boy'}]},
'6800_00A21E00':{'1':[{'val':'3.0.0.2222'}]},
'6800_00823400':{'1':[{'low':3000,'high':3000,'val':3000}]},
'6800_08822B00':{'1':[{'val':'SMA'}]},
'6800_08822000':{'1':[{'val':'Sunny Boy 3.0'}]}
}}}";
var json = JObject.Parse(response);
var json_serial = json["result"].First.Children<JObject>().ToList()[0];
foreach(var token in json_serial)
{
var tokenKey = token.Key;
var tokenVal = token.Value.SelectToken("$.1[0].val");
jObjectResult.Add(tokenKey, tokenVal);
}

You could use SelectTokens with the recursive descent operator .. to find all the val properties, then walk up the chain using .Parent repeatedly to get the corresponding key. Create new JProperties from this information and put them into a new JObject to get your result. Here is a "one-liner":
var result = new JObject(
JObject.Parse(response)
.SelectTokens("$..val")
.Select(jt => new JProperty(
((JProperty)jt.Parent.Parent.Parent.Parent.Parent.Parent).Name,
jt
))
);
Fiddle: https://dotnetfiddle.net/TbZ7LS

At the end with some pointers form #Brian Rogers I came with the following solution:
// Arrange
var response = #"{'result':{'0199 - B344EE33':
{
'6800_10821E00':{'1':[{'val':'SMA Sunny Boy'}]},
'6800_00A21E00':{'1':[{'val':'3.0.0.2222'}]},
'6800_00823400':{'1':[{'low':3000,'high':3000,'val':3000}]},
'6800_08822B00':{'1':[{'val':'SMA'}]},
'6800_08822000':{'1':[{'val':'Sunny Boy 3.0'}]}
}}}";
// Act
var json = JObject.Parse(response);
var json_serial = (JProperty)json["result"].First();
var jObjectResult = new JObject(
json_serial.Value.Select(p =>
{
return new JProperty(
((JProperty)p).Name,
p.First.SelectToken("$.1[0].val")
);
}));

Related

Parse random String & return Value (JSON)

Edit: It works pretty well now and this makes it possible to reference URLs in a JSON file and return their related pairs (e.g game name / year / image url). Here's the code.
AFRAME.registerComponent('jfetch', {
schema: {},
init: function () {
var url = 'json/text.json';
var request = new XMLHttpRequest();
request.open( 'GET', url, true );
request.addEventListener( 'load', function ( event ) {
var jsongames = JSON.parse( event.target.response )
var keys = Object.keys(jsongames);
var random = jsongames[keys.length * Math.random() << 0];
var games = random.Title + ' (' + random.Developer + ')'
var textEntity = document.querySelector('#text');
textEntity.setAttribute("value", games)
var gurl = random.Imageurl
var sceneEl = document.querySelector('a-scene');
sceneEl.querySelector('a-box').setAttribute('material', {src:gurl});
} );
request.send( null );
}
});
Thanks for the help everyone!
Original Question: I would like to fetch a random "Title" string in my Json file and return its corresponding value. I know the simple test code works but I have no idea how to apply it to an array with lots of objects and to add the random parsing element. Can someone please help me with a solution? This is my remix file.
AFRAME.registerComponent('json-text-loader', {
schema: {},
init: function () {
var textEntity = document.querySelector('#text');
var url = 'json/text.json';
var request = new XMLHttpRequest();
request.open( 'GET', url, true );
request.addEventListener( 'load', function ( event ) {
var jsonGames = JSON.parse( event.target.response )
textEntity.setAttribute("value", jsonGames.Title)
} );
request.send( null );
}
});
You can not manipulate JSON file as you would with an object, because JSON is a string. Thats why we parse them (converting into Javascript object).
From your question I assume that you want to get a random value of key-value pairs, where key is a Title. In that case, first you parse JSON response (as you do already - var jsonGames = JSON.parse( event.target.response )). So now you have your Javascript object to work with - jsonGames and all what is left is to get that random key of it. To do that you can, for ex:
var jsonGames = JSON.parse( event.target.response )
var keys = Object.keys(jsonGames);
var random = jsonGames[keys[keys.length * Math.random() << 0]];
textEntity.setAttribute("value", random.Title)
Please comment if something is not right.

How to get property from JSON model filled with oData?

Im trying to get property from oData return model. I set data in success callback function from oData to JSON model.
oODataModel.read("/ConnObjSet?$filter=Objecttype eq 'CONNOBJ' and ConnObject eq '20000000002'",
true,
true,
false,
function _OnSuccess(oData, oResponse){
var oJSON = new sap.ui.model.json.JSONModel();
oJSON.setData(oData);
sap.ui.getCore().setModel(oJSON, "ConnectionObject");
},
This is my JSON object in console log and highlighted property I want to get. I want to get every 15 Buspartner number from whole array.
And this is what I tried to get property:
var oLog = sap.ui.getCore().getModel("ConnectionObject").oData.results;
console.log(oLog);
If you have an array of objects, you can get an array of properties from each of these objects by using the Array.map() function.
So in your case:
var aResults = this.getView().getModel().getProperty("/results");
var aBuspartner = aResults.map(function (r) { return r.Buspartner});
var oJSONModel = new sap.ui.model.json.JSONModel();
oJSONModel.setProperty("/resultarray", aBuspartner)
Please try:
var aResults = this.getView().getModel().getProperty("/results");
var oJSONModel = new sap.ui.model.json.JSONModel();
oJSONModel.setProperty("/resultarray",new Array())
for(var i = 0; i<aResults.lenght;i++){
oJSONModel.getProperty("/resultarray").push(aResults[i].Buspartner)
}
You could also try to add a filter and select to your oData.read
The oData-URL
http://services.odata.org/V2/Northwind/Northwind.svc/Products
selects all Product with all their properties
http://services.odata.org/V2/Northwind/Northwind.svc/Products?$filter=UnitsInStock%20eq%2017
shows only Products with "UnitsInStock=17"
http://services.odata.org/V2/Northwind/Northwind.svc/Products?$select=ProductID&$filter=UnitsInStock%20eq%2017
selects only the ProductID of Products with "UnitsInStock=17"
so
oODataModel.read("/ConnObjSet?$select=Buspartner&$filter=Objecttype eq 'CONNOBJ' and ConnObject eq '20000000002'"
...
should get the filtered Buspartners directly.

How to get nested deep property value from JSON where key is in a variable?

I want to bind my ng-model with JSON object nested key where my key is in a variable.
var data = {"course":{"sections":{"chapter_index":5}}};
var key = "course['sections']['chapter_index']"
Here I want to get value 5 from data JSON object.
I found the solution to convert "course.sections.chapter_index" to array notation like course['sections']['chapter_index'] this. but don't know how to extract value from data now
<script type="text/javascript">
var BRACKET_REGEXP = /^(.*)((?:\s*\[\s*\d+\s*\]\s*)|(?:\s*\[\s*"(?:[^"\\]|\\.)*"\s*\]\s*)|(?:\s*\[\s*'(?:[^'\\]|\\.)*'\s*\]\s*))(.*)$/;
var APOS_REGEXP = /'/g;
var DOT_REGEXP = /\./g;
var FUNC_REGEXP = /(\([^)]*\))?$/;
var preEval = function (path) {
var m = BRACKET_REGEXP.exec(path);
if (m) {
return (m[1] ? preEval(m[1]) : m[1]) + m[2] + (m[3] ? preEval(m[3]) : m[3]);
} else {
path = path.replace(APOS_REGEXP, '\\\'');
var parts = path.split(DOT_REGEXP);
var preparsed = [parts.shift()]; // first item must be var notation, thus skip
angular.forEach(parts, function (part) {
preparsed.push(part.replace(FUNC_REGEXP, '\']$1'));
});
return preparsed.join('[\'');
}
};
var data = {"course":{"sections":{"chapter_index":5}}};
var obj = preEval('course.sections.chapter_index');
console.log(obj);
</script>
Hope this also help others. I am near to close the solution,but don't know how can I get nested value from JSON.
This may be a good solution too
getDeepnestedValue(object: any, keys: string[]) {
keys.forEach((key: string) => {
object = object[key];
});
return object;
}
var jsonObject = {"address": {"line": {"line1": "","line2": ""}}};
var modelName = "address.line.line1";
var result = getDescendantPropValue(jsonObject, modelName);
function getDescendantPropValue(obj, modelName) {
console.log("modelName " + modelName);
var arr = modelName.split(".");
var val = obj;
for (var i = 0; i < arr.length; i++) {
val = val[arr[i]];
}
console.log("Val values final : " + JSON.stringify(val));
return val;
}
You are trying to combine 'dot notation' and 'bracket notation' to access properties in an object, which is generally not a good idea.
Source: "The Secret Life of Objects"
Here is an alternative.
var stringInput = 'course.sections.chapter_index'
var splitInput = stringInput.split(".")
data[splitInput[1]]][splitInput[2]][splitInput[3]] //5
//OR: Note that if you can construct the right string, you can also do this:
eval("data[splitInput[1]]][splitInput[2]][splitInput[3]]")
Essentially, if you use eval on a string, it'll evaluate a statement.
Now you just need to create the right string! You could use the above method, or tweak your current implementation and simply go
eval("data.course.sections.chapter_index") //5
Source MDN Eval docs.
var data = {
"course": {
"sections": {
"chapter_index": 5
}
}
};
var key = "course['sections']['chapter_index']";
var keys = key.replace(/'|]/g, '').split('[');
for (var i = 0; i < keys.length; i++) {
data = data[keys[i]];
}
console.log(data);
The simplest possible solution that will do what you want:
var data = {"course":{"sections":{"chapter_index":5}}};
var key = "course['sections']['chapter_index']";
with (data) {
var value = eval(key);
}
console.log(value);
//=> 5
Note that you should make sure key comes from a trusted source since it is eval'd.
Using with or eval is considered dangerous, and for a good reason, but this may be one of a few its legitimate use cases.
If you don't want to use eval you can do a one liner reduce:
var data = {"course":{"sections":{"chapter_index":5}}};
var key = "course['sections']['chapter_index']"
key.split(/"|'|\]|\.|\[/).reduce((s,c)=>c===""?s:s&&s[c], data)

Unable to store and retrieve JSON value by JQUERY

I have two textbox(goalText and goalText1) and a button(goalreach) in my html.
My aim : When I enter numeric value in 1 textbox(goalText), it should be converted to json and be stored. So even after 5 days when I run the application, it should be stored. Now when I enter the numeric value, in other textbox(goalText1) and it matches, I am simply displaying the message match. This is the demo, I am trying so that I can know that value can be stored in json and can be retrieved when necessary. I have written the code as follow:
$("#goalreach").click(function () {
var contact = new Object();
contact.goalDist = "$("#goalText.value ").val()";
var jsonText = JSON.stringify(contact);
if (jsonText == ($("#goalText1.value").val())) {
document.getElementById('divid').innerHTML = 'Match';
}
});
I know, I have made many simple mistakes of brackets and " too, but I am a newbie, If you can help me out.
First, you have to compare either 2 objects or 2 strings, and in goalDist, you should store the value (BTW, you get the jQuery object with $("#goalText") and the value with somejQueryObject.val() moreover this is generally equivalent to document.getElementById("goalText").value)...
This can be done like this :
$("#goalreach").click(function () {
// Create an object with the single property "goalDist"
var contact = { goalDist : $("#goalText").val() };
// Makes it be a string (it will in this simple example : `"{"goalDist":<the value of goalTest>}"`
var jsonText = JSON.stringify(contact);
// Creates a string from an equivalent object bound on the second field
var jsonText2 = JSON.stringify({ goalDist : $("#goalText2").val() });
// Compares the 2 strings
if (jsonText === jsonText2) {
document.getElementById('divid').innerHTML = 'Match';
}
});
TRY THIS
$("#goalreach").click(function () {
var contact = new Object();
var goalDist = '$("#goalText.value").val()';
var jsonText = JSON.stringify(contact.goalDist);
if(jsonText==($("#goalText1.value").val()))
{
document.getElementById('divid').innerHTML = 'Match';
}
});
Try the following code:
$("#goalreach").click(function () {
var contact = new Object();
contact.goalDist = $("#goalText").val();
var jsonText = JSON.stringify(contact);
if (jsonText == ($("#goalText1").val())) {
document.getElementById('divid').innerHTML = 'Match';
}
});
OR
$("#goalreach").click(function () {
var goalText = $("#goalText").val();
var goalText1 = $("#goalText1").val();
if (goalText == goalText1) {
document.getElementById('divid').innerHTML = 'Match';
}
});

actionscript arrays merge

I posted my problem a few hours ago, but I think I figured out how to ask my question in a more comprehensible way.
This is my code:
// 1. Intro
var introPL1:Array = ["intro1","intro2","intro3","intro4"];
var introPL2:Array = ["intro5","intro6","intro7","intro8","intro9"];
var introPL3:Array = ["intro10","intro11"];
var introPL4:Array = ["intro12","intro13"];
var allIntro:Array = [introPL1,introPL2,introPL3,introPL4];
// 2. Clothes
var clothesPL1:Array = ["clothes1","clothes2","clothes3","clothes4","clothes5"];
var clothesPL2:Array = ["clothes6","clothes7","clothes8"];
var clothesPL3:Array = ["clothes9","clothes10"];
var clothesPL4:Array = ["clothes11","clothes12","clothes13"];
var allClothes:Array = [clothesPL1,clothesPL2,clothesPL3,clothesPL4];
// 3. Colored Numbers
var colNumPL1:Array = ["colNum1","colNum2","colNum3","colNum4","colNum5"];
var colNumPL2:Array = ["colNum6","colNum7","colNum8"];
var colNumPL3:Array = ["colNum9","colNum10"];
var colNumPL4:Array = ["colNum11","colNum12","colNum13"];
var allColNum:Array = [colNumPL1,colNumPL2,colNumPL3,colNumPL4];
var allStuff:Array;
allStuff = allIntro.concat(allClothes, allColNum);
trace(allStuff[4]);
When I trace allStuff[4] it displays "clothes1,clothes2,clothes3,clothes4,clothes5".
The thing is, I would like all the stuff to be in the allStuff array (without sub-arrays) and when I trace allStuff[4], I would like it to display "intro5" (the fifth item in the huge allStuff array).
the function you want to use then is concat
here's the example from adobe
var numbers:Array = new Array(1, 2, 3);
var letters:Array = new Array("a", "b", "c");
var numbersAndLetters:Array = numbers.concat(letters);
var lettersAndNumbers:Array = letters.concat(numbers);
trace(numbers); // 1,2,3
trace(letters); // a,b,c
trace(numbersAndLetters); // 1,2,3,a,b,c
trace(lettersAndNumbers); // a,b,c,1,2,3
it's pretty straight forward:
allStuff= allStuff.concat(introPL1,introPL2,introPL3,introPL4,clothesPL1,clothesPL2,clothesPL3,clothesPL4,colNumPL1,colNumPL2,colNumPL3,colNumPL4);
you could also do a
allStuff = []
for each(var $string:String in $arr){
allStuff.push($string)
}
for each array, or make it into a function
Okay, once you have declared your arrays like so, you need an additional operation to flatten your arrays allClothes and so on. Do like this:
function flatten(a:Array):Array {
// returns an array that contains all the elements
// of parameter as a single array
var b:Array=[];
for (var i:int=0;i<a.length;i++) {
if (a[i] is Array) b=b.concat(flatten(a[i]));
else b.push(a[i]);
}
return b;
}
What does it do: The function makes an empty array first, then checks the parameter member by member, if the i'th member is an Array, it calls itself with that member as a parameter, and adds the result to its temporary array, otherwise it's just pushing next member of a into the temporary array. So, to make your allIntro a flat array, you call allIntro=flatten(allIntro) after declaring it as you did. The same for other arrays.