How to hyperlink the character in paragraph which coming in Json data - html

Problem Statement :
I am getting a JSON data with Paragraph and LinkLocation(location for hiperlink the characters in the paragraph using LinkLocation:(6,12)). It means, character 6 to character 12 in the paragraph we need to hyperlink and redirect that to another page. Please advice me how to do that.
link:{id: 3, index: "Law 1.1", name: "Number of Players ",…}
content:"Law 1.1 shall be replaced by the following."
description:"Law 1.1 shall be replaced by the following:"
id:3
index:"Law 1.1"
ischanged:false
iscollapsed:false
islinked:false
isread:false
linkid:0
linktype:0
name:"Number of Players "
linkposition:"1, 6"
This is my JSON data. from this data i want to hyperlink the "content" paragraph as per the "Linkposition". for example here the link position is "1,6". so i want to hyperlink the "Law 1.1" in the content Paragraph.

If you want to hyperlink a subset of characters in a string you can do it this way:
var data = {
paragraph: "hello world",
link: '1,5'
}
var limits = link.split(',');
//subtract one cos substring method is inclusive of bottom limit and exclusive of upper limit
var lowerLimit = limits[0]-1;
var upperLimit = limits[1];
var newParagraph = data.paragraph.substr(0, lowerLimit) + "<a href='otherpage.html'>" + data.paragraph.substr(lowerLimit, upperLimit) + "</a>" + data.paragraph.substr(upperLimit, data.parapgraph.length);
So that would produce the result
<a href='otherpage.html'>Hello</a> world
Hence 'Hello' is hyperlinked

Try this code... I have added a function addLinksToParagraph(paragraph, linkLocation, location) which might help you.
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
</head>
<body>
<script>
var jsonData = {
paragraph : 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
linkLocation : '1,6',
}
$('p').html(addLinksToParagraph(jsonData.paragraph, jsonData.linkLocation, "/any_location.html"));
function addLinksToParagraph(paragraph, linkLocation, location) {
var splitArray = linkLocation.split(',');
var start = parseInt(splitArray[0]);
var end = parseInt(splitArray[1]);
var preLink = paragraph.substr(0, start); //part before the hyperlink part
var link = paragraph.substr(start, end); //the actual hyperlink part
var postLink = paragraph.substr(end + 1); //part after hyperlink part
console.log(preLink);
console.log(link);
console.log(postLink);
return preLink + '' + link + '' + postLink;
}
</script>
</body>
</html>
This will produce following output.

Related

TYPO3 render full t3:// links from bodytext in utility files

I have a headless TYPO3 installation and i need to render all the content elements as json. So far so good. The only problem i have right now is to replace the t3:// links with the full URLs since i do not have the frontend to take care of it. So the question is:
How do i replace the intern TYPO3 links in a bodytext (RTE) to full URLs?
I have tried the following but it dint really help:
$cObj->stdWrap_HTMLparser($element['bodytext']
Best regards
So i examined the TYPO3\CMS\Fluid\ViewHelpers\Format\HtmlViewHelper to get some ideas. It is actually very easy to do it.
Note: I have only tested this with t3://page?uid= and it works. The moment i find other use cases as well, i will update this answer
This code happens on my Utility class under the my_ext/Classes/Utility/MyUtility.
I first inject the TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer with DI (Dependency Injection)
/**
* #var ContentObjectRenderer
*/
protected ContentObjectRenderer $cObj;
/**
* #param ContentObjectRenderer $cObj
*/
public function __construct(
ContentObjectRenderer $cObj
) {
$this->cObj = $cObj;
}
Now i can use the parseFunc function to replace the links, with full URls (without the base url). BUT we have to define what kind of reference this function will get, which in my case would be the lib.parseFunc. So this is how it looks like:
Sometimes you only need the first and second parameters and you can leave the reference empty. You have to experiment a bit and make it work according to your needs.
public function my_module(array $teaserHomepage): array
{
$parseFuncTSPath = 'lib.parseFunc';
$newConstructedArray = [];
foreach ($teaserHomepage['fields'] as $element) {
...
$newConstructedArray['fields']['bodytext'] = $this->cObj->parseFunc($element['bodytext'], [], '< ' . $parseFuncTSPath);
}
return $newConstructedArray;
}
The before text:
<p>sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam.</span><br /> <br /> </p>
The after text:
<p>sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam.</span><br> <br> </p>
Hopefully it helped someone
Best regards

React Js axios returns empty div before actual data

I'm working on a simple app, where info from JSON should be added on a page. I was able to fetch data from a local JSON file using Axios and display it. The problem is that app renders an empty array(of the selected data) first, and only after that the actual data itself.
local json file:
{
"home": [
{
"id": "app",
"management": [
{
"id": "image",
"alt": "truck",
"img": "./img/assets/img.png",
"img2": "./img/assets/img2.png",
"img3": "./img/assets/img3.png"
},
{
"id": "services",
"title": "Managementt",
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis
aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat
nulla pariatur."
}
]
}
]
My code to fetch data from local JSON is:
const [services, setServices] = useState([]);
const getServices = async () => {
const response = await axios.get("./home.json");
setServices(response.data.home[2].management);
console.log(response);
};
useEffect(() => {
getServices();
}, []);
then it gets displayed using this code:
return (
<>
<Layout>
{services.map(({
img,
img2,
img3,
id,
title,
text,
}) => (
<>
<div className={styles.flex}>
{id === "image" ? (
<img
id={id}
className={styles.logo}
srcSet={`${img2} 2x,
${img3} 3x`}
alt={alt}
src={img}
/>
) : null}
</div>
<div>
{id === "services" ? (
<div className={styles.services} key={id}>
<div style={{ display: "flex" }}>
<h1 className={styles.text}>{title}</h1>
<p>{text}</p>
</div>
) : null}
</div>
</div>
</>
)
)}
</Layout>
</>
What happens is before actual image/text gets displayed, the app renders an empty div that can bee seen in console.log(has the same className and parameters as the rendered data, for example, if text's div has a width of 400px, next to the image there is an empty div with 400px width also) and it's messing up all styles. I want to display image and the text as flex(next to each other on the page), but when I use display flex, text's empty array displays first and takes the space near the image, and the actual text gets displayed below the image.
Please see a link to the image how I want to style text and image flex image-text
I also have to specify the id of the element, otherwise all the images from json file will be rendered.
Any suggestions will be appreciated greatly. Thank you
you have to ckeck before rendering that data exists or not like this
if(services.length>0)
{
return (
<>
<Layout>
{services.map(({
img,
img2,
img3,
id,
title,
text,
}) => (
<>
<div className={styles.flex}>
{id === "image" ? (
<img
id={id}
className={styles.logo}
srcSet={`${img2} 2x,
${img3} 3x`}
alt={alt}
src={img}
/>
) : null}
</div>
<div>
{id === "services" ? (
<div className={styles.services} key={id}>
<div style={{ display: "flex" }}>
<h1 className={styles.text}>{title}</h1>
<p>{text}</p>
</div>
) : null}
</div>
</div>
</>
)
)}
</Layout>
</>
}
else{
return <div> Loading...</div>
}

How to extract nested fields from MongoDB?

So my problem is that I have a database structure (designed by someone else and I have to work on it now) as follows:
DBS:
Database 1
Database 2
Database 3
Collection 1
Collection 2
field_1
field_1_1
field_1_1_1
field_1_2
field_2
field_3
Collection 3
Collection 4
Database 4
Now I want to extract the field field_1_1_1 any idea how I can query that?
So far I have tried applying find_one on Database 3.Collection 2.filed_1.field_1_1.field_1_1_1 but obviously it did not work.
So here goes the actual content as requested. This is what 1 item in the collection "tempStorage" under the database "workApp" looks like.
{"_id":{"tag":"i4x","org":"Temp","course":"CXV_08","category":"about","name":"overview","revision":null},
"definition":
{"data":
{"data":
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
uis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
onsequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
illum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
roident, sunt in culpa qui officia deserunt mollit anim id est laborum"
}
}
}
Edit: Uploaded the actual fields.
What does work is if I export the entire collection and then parse through it but the data is already .4 GB and I do not think that that can be the only option and that there must exist something better.
Anyone with good experience in MongoDB who can help me out?
Try this:
var data = db.tempStorage.find()
data[0].definition.data.data
Here, db.tempStorage.find() will give you all the results in an Array variable data, which you can iterate by passing an index value and using dot notation to reach out deep into the document as I have done in data[0].definition.data.data.
If you have only 1 document within collection than findOne() can also be used.
var data = db.tempStorage.findOne()
data.definition.data.data
HTH!
Thanks.

How to Achieve Just the Ctrl + A Functionality of Contenteditable Attribute?

I'm trying to display a div with some example code for users. I want them to be able to select inside the div and use Ctrl + A to select all of the example code, but I don't want them to be able to edit the actual text (lest the remove a bit on accident and then it won't work).
I'm achieving this right now through contenteditable set on the div, but how do I get the same functionality of this attribute sans the actual text editing?
EDIT: Looking at the solution linked in #Mr. Llama's comment, I can use this method to achieve the primary functionality I'm looking for. However, if possible I would like to simply allow for the Ctrl + A command my users are familiar with, and still allow for the manual highlighting of snippets of the div's text. Again, all while disallowing the addition or removal of any text.
Seems to work for me when I prevent the onkeydown, oncut and onpaste events.
for (const elm of document.getElementsByClassName('editable-not-editable')) {
elm.setAttribute('contenteditable', true);
elm.spellcheck = false;
elm.oncut = () => false;
elm.onpaste = () => false;
elm.onkeydown = (event) => {
if (event.metaKey || event.ctrlKey) {
return;
}
event.preventDefault();
}
}
<div class="editable-not-editable">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute
irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia
deserunt mollit anim id est laborum.
</div>

Getting inside JSON directory?

JSON:
{"status":"ok","count":4,"count_total":4,"pages":1,"posts":[{"id":15,"type":"post","slug":"sg-and-t13-friends-again","url":"http:\/\/example.com.com\/instanews\/sg-and-t13-friends-again\/","status":"publish","title":"SG and T13 friends again","title_plain":"SG and T13 friends again","content":"<p>again?<\/p>\n","excerpt":"<p>again?<\/p>\n","date":"2014-10-08 20:28:52","modified":"2014-10-08 20:28:52","categories":[{"id":2,"slug":"selena-gomez","title":"Selena Gomez","description":"","parent":0,"post_count":3},{"id":3,"slug":"taylor-swift","title":"Taylor Swift","description":"","parent":0,"post_count":2}],"tags":[],"author":{"id":1,"slug":"admin","name":"admin","first_name":"","last_name":"","nickname":"admin","url":"","description":""},"comments":[],"attachments":[{"id":16,"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500.png","slug":"tumblr_nc5rkwqj1r1tv3z6lo1_500","title":"tumblr_nc5rkwQj1R1tv3z6lo1_500","description":"","caption":"","parent":15,"mime_type":"image\/png","images":{"full":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500.png","width":500,"height":630},"thumbnail":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500-150x150.png","width":150,"height":150},"medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500-238x300.png","width":238,"height":300},"large":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500.png","width":500,"height":630},"vw_small":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500-360x200.png","width":360,"height":200},"vw_square_small":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500-360x360.png","width":360,"height":360},"vw_medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500-500x420.png","width":500,"height":420},"vw_square_medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500.png","width":500,"height":630},"vw_large":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500.png","width":500,"height":630}}}],"comment_count":0,"comment_status":"open","thumbnail":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500-150x150.png","custom_fields":{"vw_review_average_score":["0"],"vw_post_featured":["0"],"vw_post_layout":["right"],"vw_enable_review":["0"]},"thumbnail_size":"thumbnail","thumbnail_images":{"full":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500.png","width":500,"height":630},"thumbnail":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500-150x150.png","width":150,"height":150},"medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500-238x300.png","width":238,"height":300},"large":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500.png","width":500,"height":630},"vw_small":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500-360x200.png","width":360,"height":200},"vw_square_small":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500-360x360.png","width":360,"height":360},"vw_medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500-500x420.png","width":500,"height":420},"vw_square_medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500.png","width":500,"height":630},"vw_large":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_nc5rkwQj1R1tv3z6lo1_500.png","width":500,"height":630}}},{"id":9,"type":"post","slug":"selena-gomez-new-trailer","url":"http:\/\/example.com.com\/instanews\/selena-gomez-new-trailer\/","status":"publish","title":"Selena Gomez new trailer","title_plain":"Selena Gomez new trailer","content":"<p>Not really\u00a0“Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.”<\/p>\n","excerpt":"<p>Not really\u00a0“Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, …<\/p>\n","date":"2014-10-08 20:22:02","modified":"2014-10-08 20:25:19","categories":[{"id":2,"slug":"selena-gomez","title":"Selena Gomez","description":"","parent":0,"post_count":3}],"tags":[],"author":{"id":1,"slug":"admin","name":"admin","first_name":"","last_name":"","nickname":"admin","url":"","description":""},"comments":[],"attachments":[{"id":11,"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842.jpg","slug":"img_1842","title":"IMG_1842","description":"","caption":"","parent":9,"mime_type":"image\/jpeg","images":{"full":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842.jpg","width":1280,"height":1024},"thumbnail":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842-150x150.jpg","width":150,"height":150},"medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842-300x240.jpg","width":300,"height":240},"large":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842-1024x819.jpg","width":1024,"height":819},"vw_small":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842-360x200.jpg","width":360,"height":200},"vw_square_small":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842-360x360.jpg","width":360,"height":360},"vw_medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842-750x420.jpg","width":750,"height":420},"vw_square_medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842-750x750.jpg","width":750,"height":750},"vw_large":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842-1140x641.jpg","width":1140,"height":641}}}],"comment_count":0,"comment_status":"open","thumbnail":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842-150x150.jpg","custom_fields":{"vw_review_average_score":["0"],"vw_post_featured":["0"],"vw_post_layout":["right"],"vw_enable_review":["0"]},"thumbnail_size":"thumbnail","thumbnail_images":{"full":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842.jpg","width":1280,"height":1024},"thumbnail":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842-150x150.jpg","width":150,"height":150},"medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842-300x240.jpg","width":300,"height":240},"large":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842-1024x819.jpg","width":1024,"height":819},"vw_small":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842-360x200.jpg","width":360,"height":200},"vw_square_small":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842-360x360.jpg","width":360,"height":360},"vw_medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842-750x420.jpg","width":750,"height":420},"vw_square_medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842-750x750.jpg","width":750,"height":750},"vw_large":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/IMG_1842-1140x641.jpg","width":1140,"height":641}}},{"id":7,"type":"post","slug":"taylor-swift-new-album","url":"http:\/\/example.com.com\/instanews\/taylor-swift-new-album\/","status":"publish","title":"Taylor Swift new album","title_plain":"Taylor Swift new album","content":"<p>3 weeks!\u00a0Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.<\/p>\n<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.<\/p>\n","excerpt":"<p>3 weeks!\u00a0Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, …<\/p>\n","date":"2014-10-08 20:21:20","modified":"2014-10-08 20:27:44","categories":[{"id":3,"slug":"taylor-swift","title":"Taylor Swift","description":"","parent":0,"post_count":2}],"tags":[],"author":{"id":1,"slug":"admin","name":"admin","first_name":"","last_name":"","nickname":"admin","url":"","description":""},"comments":[],"attachments":[{"id":14,"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500.jpg","slug":"tumblr_ncqmsrndkv1rx2xpto1_500","title":"tumblr_ncqmsrndkV1rx2xpto1_500","description":"","caption":"","parent":7,"mime_type":"image\/jpeg","images":{"full":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500.jpg","width":500,"height":648},"thumbnail":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500-150x150.jpg","width":150,"height":150},"medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500-231x300.jpg","width":231,"height":300},"large":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500.jpg","width":500,"height":648},"vw_small":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500-360x200.jpg","width":360,"height":200},"vw_square_small":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500-360x360.jpg","width":360,"height":360},"vw_medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500-500x420.jpg","width":500,"height":420},"vw_square_medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500.jpg","width":500,"height":648},"vw_large":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500-500x641.jpg","width":500,"height":641}}}],"comment_count":0,"comment_status":"open","thumbnail":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500-150x150.jpg","custom_fields":{"vw_review_average_score":["0"],"vw_post_featured":["0"],"vw_post_layout":["right"],"vw_enable_review":["0"]},"thumbnail_size":"thumbnail","thumbnail_images":{"full":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500.jpg","width":500,"height":648},"thumbnail":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500-150x150.jpg","width":150,"height":150},"medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500-231x300.jpg","width":231,"height":300},"large":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500.jpg","width":500,"height":648},"vw_small":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500-360x200.jpg","width":360,"height":200},"vw_square_small":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500-360x360.jpg","width":360,"height":360},"vw_medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500-500x420.jpg","width":500,"height":420},"vw_square_medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500.jpg","width":500,"height":648},"vw_large":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/tumblr_ncqmsrndkV1rx2xpto1_500-500x641.jpg","width":500,"height":641}}},{"id":5,"type":"post","slug":"selena-gomez-reported-pregnant","url":"http:\/\/example.com.com\/instanews\/selena-gomez-reported-pregnant\/","status":"publish","title":"Selena Gomez reported pregnant","title_plain":"Selena Gomez reported pregnant","content":"<p>yolo? fake!<\/p>\n","excerpt":"<p>yolo? fake!<\/p>\n","date":"2014-10-08 20:20:17","modified":"2014-10-08 20:26:23","categories":[{"id":2,"slug":"selena-gomez","title":"Selena Gomez","description":"","parent":0,"post_count":3}],"tags":[],"author":{"id":1,"slug":"admin","name":"admin","first_name":"","last_name":"","nickname":"admin","url":"","description":""},"comments":[],"attachments":[{"id":12,"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot.jpg","slug":"selena-gomez-photoshoot","title":"Selena Gomez - Photoshoot","description":"","caption":"","parent":5,"mime_type":"image\/jpeg","images":{"full":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot.jpg","width":720,"height":541},"thumbnail":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot-150x150.jpg","width":150,"height":150},"medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot-300x225.jpg","width":300,"height":225},"large":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot.jpg","width":720,"height":541},"vw_small":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot-360x200.jpg","width":360,"height":200},"vw_square_small":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot-360x360.jpg","width":360,"height":360},"vw_medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot-720x420.jpg","width":720,"height":420},"vw_square_medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot.jpg","width":720,"height":541},"vw_large":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot.jpg","width":720,"height":541}}}],"comment_count":0,"comment_status":"open","thumbnail":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot-150x150.jpg","custom_fields":{"vw_review_average_score":["0"],"vw_post_featured":["0"],"vw_post_layout":["right"],"vw_enable_review":["0"]},"thumbnail_size":"thumbnail","thumbnail_images":{"full":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot.jpg","width":720,"height":541},"thumbnail":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot-150x150.jpg","width":150,"height":150},"medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot-300x225.jpg","width":300,"height":225},"large":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot.jpg","width":720,"height":541},"vw_small":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot-360x200.jpg","width":360,"height":200},"vw_square_small":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot-360x360.jpg","width":360,"height":360},"vw_medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot-720x420.jpg","width":720,"height":420},"vw_square_medium":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot.jpg","width":720,"height":541},"vw_large":{"url":"http:\/\/example.com.com\/instanews\/wp-content\/uploads\/Selena-Gomez-Photoshoot.jpg","width":720,"height":541}}}],"query":{"ignore_sticky_posts":true}}
I'm trying to get the full picture from the first post. My solution (which works):
let urlPath = "http://example.com/instanews/api/get_posts/"
let url: NSURL = NSURL(string: urlPath)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in
println("Task completed")
if((error) != nil) {
// If there is an error in the web request, print it to the console
println(error.localizedDescription)
}
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
if(err != nil) {
// If there is an error parsing JSON, print it to the console
println("JSON Error \(err!.localizedDescription)")
} else {
var result: AnyObject = jsonResult["posts"]! as NSArray
var result2: AnyObject = result[0]!
var result3: AnyObject = result2["attachments"]!!
var result4: AnyObject = result3[0]!
var result5: AnyObject = result4["images"]!!
var result6: AnyObject = result5["full"]!!
var result7: AnyObject = result6["url"]!!
println(result7)
}
})
task.resume()
I'm not happy with those var result7 etc. this is obviously not the right way to do it. I'm not quite sure why can't we just use result["posts"][0] and stack it like that.
Also can you please explain why sometimes there has to be double exclamation point? I know that it is force unwrap, but why is it double?
Thanks!
You can consider to use some native swift json library that can take advantage of the Optional semantic e.g. https://github.com/owensd/json-swift
Then your code could be rewritten as
if let result7 = jsonResult["posts"]["attachments"]["images"]["full"]["url"].string {
println(result7)
}