Get the image id from image cropper property - json

I am trying to get an image ID of the Umbraco's Image Cropper property in order to use it with TypedMedia(id).GetResponsiveCropUrl() method.
I am struggling to extract only the ID. My current implementation item.GetProperty("mainImage").Value.ToString() returns JSON object consisting of additional Image Cropper data such as focal point:
{ "focalPoint": { "left": 0.71111111111111114, "top": 0.57 }, "src": "/media/1004/9910_03_7326-river-flood_web.jpg", "crops": [ { "alias": "Carousel", "width": 700, "height": 400 } ] }1156
What would be the best approach for retrieving the image ID?
This is my implementation:
foreach (Node item in Node.GetCurrent().GetDescendantNodes())
{
if (item.GetProperty<bool>("showInNewsCarousel") == true)
{
Response.Write(item.GetProperty("mainImage").Value.ToString());
// var slideImage = Umbraco.Media(item.GetProperty("mainImage").Value);
<img class="img-responsive" src="#Umbraco.TypedMedia(1155).GetResponsiveCropUrl("Carousel")" />
}
}

The 1156 value that you said in the comments was the image ID is not actually part of the JSON, but appears to have been tacked on later. (If you try to validate the string at JSONLint.com, you'll see what I mean.) Since the ID is not part of the JSON, you will not be able to use a JSON parser to get the value. I think your best bet is just to find the last closing brace and then take everything after that.
string id = json.Substring(json.LastIndexOf('}') + 1).Trim();

Related

Parsing JSON to get only specific children not all the children

I have been trying to parse the following JSON data using JSON.Parse(), I only need the url tags inside images not the caption or resizedImageUrls.
{"images": [
{
"url": "https://media.IMG_0001.jpg",
"caption": "Photo1",
"resizedImageUrls": {
"size135x100": "https://media.IMG_0001_135x100.jpg",
"size476x317": "https://media.IMG_0001_476x317.jpg",
"size656x437": "https://media.IMG_0001_656x437.jpg"
}
},
{
"url": "https://media.IMG_0002.jpg",
"caption": "Photo2",
"resizedImageUrls": {
"size135x100": "https://media.IMG_0002_135x100.jpg",
"size476x317": "https://media.IMG_0002_476x317.jpg",
"size656x437": "https://media.IMG_0002_656x437.jpg"
}
},{
"url": "https://media.IMG_0003.jpg",
"caption": "Photo3",
"resizedImageUrls": {
"size135x100": "https://media.IMG_0003_135x100.jpg",
"size476x317": "https://media.IMG_0003_476x317.jpg",
"size656x437": "https://media.IMG_0003_656x437.jpg"
}
}
]}
I declared the above JSON as variable data and then used following code.
var items = JSON.parse(data);
return {
url: items.images;
}
But it returned all the urls, captions and resized image urls. I know another method is to use items.images[0].url. But, sometimes there are lots of image urls and its not feasible to add codes from 0 to n numbers. I thought about using for loop, but, I dont know how.
You can make a map and return urls only.
const items = JSON.parse(data);
const urls = items.images.map(item => item.url);

Selecting the first JSON result after predicate

I'm trying to write a JSON path that contains a predicate not specific enough to select a single element, yet I want to force the result to be the first one. I would like to have it done using the path only (not as part of the C# code later).
The following path returns the first book, which I expected: $.book[0]
The following path returns exactly two books with price > 0, which I expected: $.book[?(#.price>20)]
Now, I would like to return the first element from the result. I was hoping for this to work, but it doesn't. Somehow this does not work at all:
$.book[?(#.price>20)][0]
I am using .NET and Json.NET library, but I am open to any other.
The example JSON is as follows:
{
"book":[
{
"title":"Beginning JSON",
"author":"Ben Smith",
"price":49.99
},
{
"title":"JSON at Work",
"author":"Tom Marrs",
"price":29.99
},
{
"title":"Learn JSON in a DAY",
"author":"Acodemy",
"price":8.99
},
{
"title":"JSON: Questions and Answers",
"author":"George Duckett",
"price":6.00
}
]
}

d3.js, using d3.extent to find min/max of nest json values

I'm building a bubble chart in d3 and I'd like the color of the bubbles to be based off of logFC values I have in a local json file.
My json file looks like this:
{
"name": "genes",
"children": [
{
"value": "9.57E-06",
"logFC": "-5.51658163",
"symbol": "BCHE",
},
{
"value": "0.0227",
"logFC": "3.17853632",
"symbol": "GRIA2",
},
{
"value": "0.00212",
"logFC": "-2.8868275",
"symbol": "GRIN2A",
}
]
}
The file is not flat which is why I think I'm having trouble referencing the leaf nodes with d3.extent. I know I could use:
var color1 = d3.scale.linear()
.domain([-5.51658163,3.17853632]) //manually putting in min/max into the domain
.range(["lightgreen", "green"]);
But my data will change, and to make the code dynamic - I've tried the following along with many other variations:
var color1 = d3.scale.linear()
.domain([d3.extent(d3.values(data, function(data) { return +d.logFC;}))])
.range(["lightgreen", "green"]);
Basically, Im having trouble using d3.extent on leaf nodes. Is there a simple way to find the min and max values using d3.extent to find the min and max values of logFC?
Thank you!
(PS if there are any problems with parenthesis it was a mistake I made when copying my data into the question box)
When I look in the console editor, I see:
d3.extent accepts an array of values and return the bounds as an array. So I guess your code should be more like:
.domain(d3.extent(d3.values(data, function(data) {
return +d.logFC;
})))
(no square brackets)
Not 100% sure, because I don't know what the data variable is in your example.
Update:
If the data variable is the loaded JSON object, do the following:
.domain(d3.extent(data.children.map(function(child) {
return +child.logFC;
})))

Push new items into JSON array

Let's say this is the table inside my collection:
{
"_id" : ObjectId("557cf6bbd8efe38c627bffdf"),
"name" : "John Doe",
"rating" : 9,
"newF" : [
"milk",
"Eggs",
"Beans",
"Cream"
]
}
Once a user types in some input, it is sent to my node server, and my node server then adds that item to the list "newF", which is then sent back to my MongoDB and saved.
I'm trying to use update, which can successfully change the values inside of this table, but I'm not sure how to add new items onto that list. I did it with $push inside the MongoDB shell, but not sure how to do it on node.
Here's a snippet of my code:
db.collection('connlist').update({ _id: new ObjectId("e57cf6bb28efe38c6a7bf6df")}, { name: "JohnDoe", rating: 9, newF: ["Milk, Eggs", "Beans"] }, function(err,doc){
console.log(doc);
});
Well the syntax for adding new items is just the same as in the shell:
// make sure you actually imported "ObjectID"
var ObjectId = require('mongodb').ObjectID;
db.collection('conlist').update(
{ "_id": new ObjectId("e57cf6bb28efe38c6a7bf6df") },
{ "$push": { "newF": { "$each": [ "cream", "butter" ] } } },
function(err,numAffected) {
// do something in the callback
}
)
Or perhaps use .findOneAndUpdate() if you want to return the modified document instead of just making the alteration.
Of course use $push and possibly with $each which allows multiple array elements to be added when adding to an array. If you want "unique" items then use $addToSet where your operation allows.
And generally speaking for other items you should use $set or other operators in the update portion of your document. Without these operators you are just "replacing" the document content with whatever structure you place in the "update" portion of your statement.

Filter JSON data based on current URL route

The problem
I'm trying to filter json data and display only a portion of it on an Angular page, based on the page's current URL.
In detail
I have a list of 100 JSON objects, and each one looks like this:
{
"name": "Evangeline Perreault",
"age_1": 1,
"total_age": 1,
"photo_small": "img/400/001_400.jpg",
"photo_medium": "img/800/001_800.jpg",
"photo_large": "img/1200/001_1200.jpg",
"photo_extralarge": "img/1600/001_1600.jpg",
"video": 67443664,
"id": 1,
"quote": "test quote here and here",
"type": 1
},
The 'type' attribute is what I want to use to filter out the subsets of my data. With that in mind, I tried to setup my URL structure to tie the type attribute here to my url. Here is my route:
angular.module('100_Ages', ['mydirectives', 'ngResponsiveImages']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/100_Ages/nav/:personType', {templateUrl: 'partials/person-list.html', controller: NavListCtrl}).
otherwise({redirectTo: '/100_Ages'});
}]);
So, I have pointed the route to the 'type' field in my JSON and I tried writing a controller to tie the two together.
function NavListCtrl($scope, $routeParams, $http) {
$http.get('person.json').success(function(data) {
angular.forEach(data, function(person) {
if (person.type == $routeParams.personType)
$scope.person = person;
});
});
}
And here is my partial template:
<div class="nav_outer"><img class="nav_img" ng-src="{{person.photo_small}}" ng-alt="{{person.name}}" /></div>
I expected this to display all the matching images for the URL type I'm on. So, if I'm on "/100_Ages/nav/3", I expected all the images (roughly 10 pictures) from the objects with a type of "3" to display. However, it only displayed the last object with a type of "3".
So, I tried an ng-repeat like so:
<div class="nav_outer" ng-repeat="person in persons"><img class="nav_img" ng-src="{{person.photo_small}}" ng-alt="{{person.name}}" /></div>
I expected that to loop through and show all the matching images, but that made nothing at all show up.
I think my problem has to do with the angular.forEach, but I'm not sure how else to tie my JSON type to the page's typeid.
Thanks for any suggestions.
The ng-repeat should work if you push each item into an array. (Also, you are referring to a 'persons' object in the ng-repeat, which doesn't exist according to code provided). So, try this:
$http.get('person.json').success(function(data) {
$scope.persons = [];
angular.forEach(data, function(person) {
if (person.type == $routeParams.personType)
$scope.persons.push(person);
// or alternatively - this.push(person), with the optional 3rd param of $scope.persons (I don't really understand that, but whatever...)
});
});
Now with the array populated, your ng-repeat="person in persons" should work.
UPDATE:
If the success object was already an array of objects, then just set the scope object to the array - no need to iterate through them:
$http.get('person.json').success(function(data) {
$scope.persons = data;
})