I am calling a rest API from angular, the rest api returns data in JSON Array of Objects like this
Now I am trying to convert it to my model class array but don't getting anywhere can you please guide me.
My Model Class
My Service File
Here it gives error on map and I don't know how to convert it to my model class array to display it in table
Resolved It.
As i was directly getting the array of objects in response, I don't need to convert it and use an interface. So here is my correct code
fetchAllGamesRecord() : Observable<Fifa[]>{
const fifaUrl = `${this.baseUrl}/fetchAllGamesRecord`;
return this.httpClient.get<Fifa[]>(fifaUrl);
}
This function is called like this
this.fifaService.fetchAllGamesRecord().subscribe(
data => {
this.allGameRecord = data;
console.log(`Data = `+data);
}
);
you can do that while calling fetchAllGamesRecord
fetchAllGamesRecord().subscribe( (response: Fifa[]) => {
// do something
}
where Fifa is interface not class
In the Spring framework also Fifa[] doesn't work in REST calls, we need to put it in another class as I showed below, I assume this will work.
export class FifaWrapper {
wrapper: Fifa[];
}
and also use this class in Observable
fetchAllGamesRecord(): Observable<FifaWrapper> {
... do you handling here
}
Related
Specifically, I'm trying to improve deserialization in my Angular project. I have a base HTTP class that abstracts away some of the universal aspects of interacting with my REST service:
import { HttpClient, HttpParams } from '#angular/common/http';
export class BaseHttpService {
...
protected get<T>(url: string, params: object = {}, options: object = {}): Observable<any> {
// some operations every get request needs to do
return this.httpClient.get<T>(url, { params: httpParams, ...options });
}
...
And I'm using the cerialize library to handle object deserialization, specifically for Java Date (millisecond since epoch format) conversion to Javascript Date, and occasionally some helper methods that I want stored on the class (as opposed to just taking the JSON in through a Typescript interface). So my use of this method always looks something like:
import { Deserialize } from 'cerialize';
import { ModelA } from './models';
export class SomeControllerService {
...
constructor(private baseHttpService: BaseHttpService) {}
someMethod<ModelA>(): Observable<ModelA> {
return this.get<ModelA>().pipe(map(response => Deserialize(response, ModelA)));
}
...
What I want to do is remove the need for .pipe(map(... which ends up being in every single method that returns a REST response object and is basically the same, just with a different model depending on the endpoint. In Java, I believe you could use the generic in the base service as an input to the Deserialize function like (response => Deserialize(response, T.class)). I also want to avoid adding another parameter to the base get function. Per my title, I could also see a solution that refactors to calling a function on the generic, that the individual models could implement specific deserialization logic in, but again, since the generic is just a type, that doesn't seem possible. Am I just running up to a limitation of Typescript?
Say we have:
class MyClass {
myProperty: string
}
Is there any built in function or easy way to get JSON like this?:
{
"myProperty": "string"
}
EDIT: My end goal is I want to dynamically print typed class definitions to a web view, in some kind of structured object syntax like JSON. I'm trying to make a server API that will return the schema for various custom classes - for example http://myserver.com/MyClass should return MyClass's properties and their types as a JSON string or other structured representation.
Evert is correct, however a workaround can look like this
class MyClass {
myProperty: string = 'string'
}
JSON.stringify(new MyClass) // shows what you want
In other words, setting a default property value lets TS compile properties to JS
If the above solution is not acceptable, then I would suggest you parsing TS files with your classes with https://dsherret.github.io/ts-simple-ast/.
Typescript class properties exist at build-time only. They are removed from your source after compiling to .js. As such, there is no run-time way to get to the class properties.
Your code snippet compiles to:
var MyClass = /** #class */ (function () {
function MyClass() {
}
return MyClass;
}());
As you can see, the property disappeared.
Based on your update, I had this exact problem. This is how I solved it.
My JSON-based API uses json-schema across the board for type validation, and also exposes these schemas for clients to re-use.
I used an npm package to automatically convert json-schema to Typescript.
This works brilliantly.
I have a class of type A.
This class has several properties, let's call them prop1, prop2 and prop3.
When I'm calling an API, that returns a JSON string representing the object, some properties might be omitted if they are null. Further down the road, however, this object is used to construct a form dynamically (using Formik, but that's unrelated).
This framework expects all properties to be there, and some will be visible dynamically depending on other properties.
So my question, how can I parse a JSON response to my custom class, keeping default values in case properties are omitted in the API response?
What I've tried was:
static getCustomer(id) {
return fetch(process.env.MD_API_URL + 'customers/' + id, { mode: 'cors' })
.then(response => {
let cust = new Customer();
return response.json().then(x => cust = JSON.parse(x));
}).catch(error => {
return error;
});
}
But this returns undefined. Must be doing something wrong...
since typescript is not actually compiled but translated into javascript so all the javascript rules apply.
Therefore deserializing json wont actually create a new instance of the class in question but gives you an object you can "call" Customer during design time.
you could however create an object and then assign the json values like this:
export class Customer {
public id: number;
public name: string;
// your stuff here
public myDefaultProp: string = "default value";
public constructor(init?: Partial<Customer>) {
Object.assign(this, init);
}
}
your return then would look like this:
return response.json().then(x => new Customer(JSON.parse(x)));
added an example https://stackblitz.com/edit/typescript-16wlmg
This essentially just a matter of determining what to do in order to create an instance of a class, and map the properties of a JSON response towards your custom class, and there could be many different ways to solve this,
But I think (Factory function) is appropriate approach for this kind of task.
how can I introduce new property into my mvc model which will hold this cities json data.
public ActionResult Edit(int id)
{
MyModel model = repository.GetById(id);
if (model.CountryId.HasValue)
{
// load cities into new property
}
return this.View(result);
}
what data type should be my property (Cities) if I want to be exposed as json on client side for further js manipulation? ICollection? Is there any recommendation for this?
Set them up as any object type you like:
MyModel model = repository.GetById(id);
if (model.CountryId.HasValue)
{
model.Cities = repository.GetCities(model.CountryId.Value);
}
return this.View(model);
Then, on the client, you can use Json.NET library to serialize it. I use this trick when I'm trying to pass an array to a client-side JS component; essentially, it serializes the array of objects into a client-side array:
#(Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.Cities))
Whatever type of object represents each city is what determines what gets rendered out to the client; it simply reads the object and renders an equivalent JS object with all the same properties. You can fine tune that by saying:
Model.Cities.Select(i => new { i.ID, i.Name, .. })
Which only includes a subset. There are also attributes you can use to exclude certain columns I believe.
Not sure if it is a bug or not. I followed some tutorial to post a Json 2D array to a ASP.NET MVC controller, and it works fine when the first element of the array is not empty, otherwise it fails.
Example: If my json obj is
var obj = {
ItemsArr: [[1, 2],[]] // first element is an array with a few elements
};
The controller will receive the data correctly. However if the first element of the 2D array is an empty array, like:
var obj = {
ItemsArr: [[], [1, 2]] // first element is an EMPTY array
};
the controller will receive a null.
I'm using jquery.json-2.3.min.js to convert objs to json strings.
The converted strings look fine:
{"ItemsArr":[[1,2],[]]}
{"ItemsArr":[[],[1,2]]}
The model code:
public class Model
{
public List<string[]> ItemsArr {get;set;}
}
public MyController : Controller
{
public ActionResult DoSomething( Model model )
{ ...
}
}
Have anyone met this problem? Any idea to solve it?
Thanks in advance!
===================================
Edit:
After some research, if I changed the empty array to null, it works.
{"ItemsArr":[null,[1,2]]}
I would suggest passing a array of objects and create a class with the Same properties on The server side, asp.net MVC will then automatically convert this array (on the JS end) into a list (or any other IEnumerable) that is a part of the action signature.