I'm using next.js and I want to fetch data from my data1.json file via getStaticProps(). The problem is that I get the error:
FetchError: invalid json response body at http://localhost:3000/data/data1.json reason: Unexpected token < in JSON at position 0
I have following code:
trainings.js (projectfolder/pages/trainings.js)
export default function Trainings({ data }) {
console.log(data);
return (
<main>
<h1>My trainings</h1>
</main>
);
}
export async function getServerSideProps() {
const res = await fetch('http://localhost:3000/data/data1.json');
const data = await res.json();
return { props: { data } };
}
data1.json (projectfolder/data/data1.json)
[
{
"name": "Jescie Duncan",
"email": "nunc#protonmail.couk",
"address": "Ap #666-9989 Nisi Avenue"
},
{
"name": "Karen Bartlett",
"email": "tellus.imperdiet#aol.couk",
"address": "P.O. Box 787, 2857 Tincidunt Ave"
},
{
"name": "Teegan Valdez",
"email": "lacus.mauris.non#hotmail.edu",
"address": "Ap #474-300 Nullam Avenue"
},
{
"name": "Stuart Silva",
"email": "nulla.donec.non#google.edu",
"address": "336-2367 Eu Ave"
}
]
Please check whether http://localhost:3000/data/data1.json api is working or not. Because Nextjs support React components as default support in the pages folder not JSON. If you want serve as API you need to use NextJS api routes which you need to specifically put logic inside api folder.
in api/data/data1.js file
import data from '/path/to/json'
async function handler(req, res) {
return res.status(200).json(data)
}
export default handler;
But a better approach is:
As you have JSON file, you directly import that data in trainings.js rather than calling an API.
import data from 'path/to/json';
export async function getServerSideProps() {
return { props: { data } };
}
Related
I have a json file that contains content for several different pages that are under a "service" category. I use dynamic routes in nextJS by having a file as "[serviceId].tsx", this routing works. However I have a json file where I want to use the [serviceId] provided in the route to access information.
I have the following code in my [serviceId].tsx file:
const json = jsonFile.services
const router = useRouter()
const serviceId = router.query.serviceId
return (
<div>
<ArticleWithPicture title={content.title} description={content.description}/>
</div>
)
}
My json file looks similar to this (ive edited it to be more clear for this example):
{
"serviceId":
[
{
"service1": {
"id": "xx",
"title": "xxx",
"description": "xx",
"featuredCompany":
[
{ "id": "1",
"name": "xxx",
"companyPageURL": "/",
"imagePath": "xxx",
"description": "xxx",
"additionalServices": {
"service1": "xxx",
"service2": "xxx"
},
"instagramURL":"/",
"twitterURL": "/"
}
]
}
},
{
"service2": {
"id": "xxx",
"title": "xxx",
"description": "xxx",
"featuredCompany":
[
{ "id": "1",
"name": "xxx",
"companyPageURL": "/",
"imagePath": "xxx",
"description": "xxx",
"additionalServices": {
"service1": "xxx",
"service2": "xx"
},
"instagramURL":"/",
"twitterURL": "/"
}
]
}
}
]
}
Basically, each Service has the content for each indiviual page. So I want to dynamically set for instance the title of my component "ArticleWithPicture" based on the corresponding title in my json file based on the serviceId that I get from router.query.serviceId. However when I try the following code:
<ArticleWithPicture title={json.{serviceId}.title}/>
I get error (this is due to how I use "{}" within a "{}", is there a way to do this better?
But I also cannot access it if I do eg:
const title = json.serviceId.title
or (what is what I actually want to do ie: query the json file based on my serviceId provided by "router.query.serviceId")
const title = json.{serviceId}.title
I guess something might be wrong with either my json file structure or how I try to access it. Any advice would be appreciated.
Thanks!
I'm assuming the JSON you provided is your entire jsonFile.
If the JSON you provided is just jsonFile.services, then change any uses of jsonFile to jsonFile.services
and update the type.
The format of the JSON isn't great for your use case because there's a lot of unnecessary wrapping.
With your current JSON
Assuming you cannot modify the format of the JSON, you would have to find the service from the serviceId array:
function getService(json, serviceId) {
return json.serviceId
.find((serviceWrapper) => serviceWrapper[serviceId] !== undefined)
?.service;
}
A fully typed example:
type Service = {
id: string
title: string
description: string
// ...
};
// you don't have to use this, I just included it for clarity
type JsonFile = {
serviceId: {
[serviceId: string]: Service
}[]
};
function getService(json: JsonFile, serviceId: string): Service | undefined {
return json.serviceId
.find((serviceWrapper) => serviceWrapper[serviceId] !== undefined)
?.service;
}
// declare const jsonFile: JsonFile;
export default function ServicePage() {
const router = useRouter();
const serviceId = router.query.serviceId as string;
const content = getService(jsonFile, serviceId);
if (!content) return (
<div>
{'Article doesn\'t exist.'}
</div>
);
return (
<div>
<ArticleWithPicture title={content.title} description={content.description} />
</div>
);
}
With better JSON
An example JSON that would need less unwrapping is:
{
"service1": {
"id": "xx",
"title": "xxx",
// ...
},
"service2": {
"id": "xxx",
"title": "xxx",
// ...
}
}
type JsonFile = {
[serviceId: string]: Service
}
Then you would be able to just do jsonFile[serviceId] or jsonFile.services[serviceId] to get a service.
I've been trying to change inline data (which worked) to external data in a JSON file.
Originally, I had this, which worked:
const treeData = [
{
name: "Parent"
attributes: {
id: 12345678
},
children: [
{
name: "Child"
attributes: {
id: 12345679
},
}
]
}
]
return(
<Tree data = {treeData}/>
)
So now I have an external JSON file that looks like this:
{
"name": "Parent",
"attributes": {
"id": 12345678,
},
"children": [
{
"name": "Child",
"attributes": {
"id": 12345679,
}
}
]
}
]
And in my program:
const[treeData, setTreeData] = useState(undefined)
const jsonSource = '../../data/tree-data.json'
/* Used to center the tree on render */
useEffect(()=> {
// Some irrelevant code here...
// Parse JSON data (Relevant)
return function parseJSONFile(){
treeUtil.parseJSON(jsonSource).
then((data) => setTreeData({data}))
.catch((error)=>console.log(error))
}
}, []);
return(
<Tree data = {treeData} />
)
Aand it does not work. Error message:
TypeError: Cannot set property 'id' of undefined
Which makes me confused because it's my first time dealing with JSON. Any insight on this can help!
You can do it in a very simple way (No need for extra works you are doing):
import treeData from "./tree-data.json"; // Import your json file (Path to your json file)
function App() {
return <Tree data={treeData} />;
}
Your code have many problems including you write your parseJSONFile in return of useEffect, Also you just defined parseJSONFile and you are not calling it, and even you call, it will be executed on component unmount (because you call it on return of useEffect), Also initial state of your treeData is undefined and it's the cause of TypeError: Cannot set property 'id' of undefined.
My codesandbox link (https://codesandbox.io/s/react-hooks-counter-demo-dh0q4?file=/src/index.js).
HttpClient.get in Angular 5 is not returning data if data is in a nested json format. The code below works for non-nested json data.
Would you please let me know if I miss anything or what would be a way to get the data?
Code:
import { HttpClient, HttpHeaders, HttpErrorResponse } from '#angular/common/http';
export class ReportService {...
searchByUser(userUrl: string): Observable<any> {
console.log('userUrl', userUrl);
return this.httpClient
.get(userUrl, { responseType: 'json' })
.catch((error: HttpErrorResponse) => {
return Observable.throw(error.status)
});
}
}
import { ReportService } from '../report.service';
this.reportService.searchByUser(userUrl).subscribe(data => {
console.log("Data :", data);
});
Nested JSON Sample Data returned by the userUrl:
[
{
"userId": "JX",
"location": "CHANTILLY, XX",
"fullName": "SMITH, JX L",
"userType": "P",
"userStatusDesc": "Active",
"occupationInfo": {
"occupationTitle": "HR GENERALIST HQ"
},
"miscInfo": {
"rankingPoints": 15,
"searchTermCount": 1
}
}
]
It looks like the issue was not with the HttpClient or nested JSON. I was able to have it working with the same JSON generated locally. And when I deployed the code it worked with the JSON generated under the same proxy.
I am trying to convert xml data to JSON in order to return it to my Angular app.
I've been able to get data but I'm not sure how to convert and return to Angular.
I am using xml2js parser plugin to convert xml.
node.js
router.get('/courselist', (req, res, next) => {
request("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml", function(error, response, body) {
console.log(body);
parser(body, function (err, result) {
res.json(response);
});
});
After parsing the output is like this:
{"gesmes:Envelope": {
"$": {
"xmlns:gesmes": "http://www.gesmes.org/xml/2002-08-01",
"xmlns": "http://www.ecb.int/vocabulary/2002-08-01/eurofxref"
},
"gesmes:subject": [
"Reference rates"
],
"gesmes:Sender": [
{
"gesmes:name": [
"European Central Bank"
]
}
],
"Cube": [
{
"Cube": [
{
"$": {
"time": "2017-09-21"
},
"Cube": [
{
"$": {
"currency": "USD",
"rate": "1.1905"
}
},
....
{
"$": {
"currency": "JPY",
"rate": "133.86"
}
},
]
}
]
}
]
}
}
Angular service
getCourseList() {
return this._http.get('./api/course-list').map(
(res: Response) => res.json()
).catch(this.handleError);
}
When I call the endpoint in Postman I can see parsed output, but in Angular I am getting error as I am not returning JSON object.
Unexpected token < in JSON at position 0
I've been looking around SO for a solution but not been able to find any which would suit me.
Can you please advise what am I doing wrong as I am beginner with Node.js
You angular service is calling './api/course-list' which is not a valid url. And, probably you have configured your server to return index.html page for even 404 page. That's why your angular client might be getting html page, and throwing the error while parsing it into `
Hope this._http.get('/api/course-list') fixes the issue.
I managed to find a solution I changed parsing to be response.body instead of body and it formatted XML properly.
Additionally paths in node.js and angular were not same.
router.get('/course-list', (req, res, next) => {
request("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml", function(error, response, body) {
var parsedBody;
var doneParsing = false;
parser(response.body, function (err, result) {
parsedBody = result;
doneParsing = true;
});
if (doneParsing === true) {
response.body = parsedBody;
}
res.json(response);
});
});
I am looking for best solution how to work with JSON in my angular2 app.
My JSON is:
{
"rightUpperLogoId": {
"id": 100000,
"value": ""
},
"navbarBackgroundColorIdCss": {
"id": 100001,
"value": ""
},
"backgroundColorIdCss": {
"id": 100002,
"value": ""
},
"translationIdFrom": {
"value": "90000"
},
"translationIdTo": {
"value": "90055"
}
}
This JSON is something like configuration file for UI of app. In my application, I want to get id from rightUpperLogoId, it is 100000. With this id I need to do GET task on my backend REST api and the returned value I would like to set to value. Thank you
You could leverage Rx operators like the flatMap one with Observable.forkJoin / Observable.of.
Here is a sample:
this.http.get('config.json')
.map(res => res.json())
.flatMap(config => {
return Observable.forkJoin(
Observable.of(config),
// For example for the request. You can build the
// request like you want
this.http.get(
`http://.../${config.rightUpperLogoId.id}`)
);
})
.map(res => {
let config = res[0];
let rightUpperLogoIdValue = res[1].json();
config.rightUpperLogoId.value = rightUpperLogoIdValue;
return config;
})
.subcribe(config => {
// handle the config object
});
This article could give you more hints (section "Aggregating data"):
http://restlet.com/blog/2016/04/12/interacting-efficiently-with-a-restful-service-with-angular2-and-rxjs-part-2/