Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deserialize issue with model decorators #97

Closed
ThawedBuffalo opened this issue May 4, 2019 · 3 comments
Closed

Deserialize issue with model decorators #97

ThawedBuffalo opened this issue May 4, 2019 · 3 comments
Assignees
Labels
invalid This doesn't seem right

Comments

@ThawedBuffalo
Copy link

Upgraded to new Angular version from 5.2.11 to 7.2.2 for an Ionic project. Deserializing throws an error indicating the model does not contain properties of required types. I used the "City" demo from your sample and was able to reproduce error. This may be a rookie mistake, but I am blocked. Any help is greatly appreciated. Attaching sample files and error message, also with link to project. Thank you for any help.
{
"resource": "/Users/jc/Documents/SW_DEV/demo-json2typescript/src/app/app.component.ts",
"owner": "typescript",
"code": "2322",
"severity": 8,
"message": "Type 'Country | Country[]' is not assignable to type 'Country'.\n Type 'Country[]' is missing the following properties from type 'Country': name, cities",
"source": "ts",
"startLineNumber": 61,
"startColumn": 7,
"endLineNumber": 61,
"endColumn": 14
}

link to project: https://github.com/ThawedBuffalo/demo-json2typescript

****************** city.ts *******************
import { JsonObject, JsonProperty} from "json2typescript";

@JsonObject("city")
export class City {
id: number = 123;

@JsonProperty("name", String)
name: string = undefined;

@JsonProperty("founded", Number)
private _founded: number = undefined;

get founded() {
    return this._founded;
}

set founded(value: number) {
    this._founded = value;
}

@JsonProperty("beautiful", Boolean)
beautiful: boolean = undefined;

@JsonProperty("data")
data: any = undefined;

@JsonProperty("keywords", [String])
keywords: string[] = undefined;

printInfo() {
    if (this.beautiful)
        console.log(this.name + " was founded in " +this.founded+ " and is really beautiful!");
    else
        console.log(this.name + " was founded in " +this.founded + ".");
}

}

************************ country.ts **********************
import { City } from "./city";
import { JsonObject, JsonProperty} from "json2typescript";

@JsonObject("Country")
export class Country {

@JsonProperty("countryName", String)
name: string = undefined;

@JsonProperty("cities", [City])
cities: City[] = undefined;

}

************************* app.component.ts ******************
import { Component, OnInit } from '@angular/core';

import { Platform } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { JsonConvert, OperationMode, ValueCheckingMode } from "json2typescript"
import { Country } from "./home/country";

@component({
selector: 'app-root',
templateUrl: 'app.component.html'
})
export class AppComponent implements OnInit {
constructor(
private platform: Platform,
private splashScreen: SplashScreen,
private statusBar: StatusBar
) {
this.initializeApp();
}

initializeApp() {
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.splashScreen.hide();
});
}

ngOnInit() {
// Define a JSON object (could come from a HTTP service, parsed with JSON.parse() if necessary)
const jsonObject: object = {
"countryName": "Switzerland",
"cities": [
{
"id": 1,
"name": "Basel",
"founded": -200,
"beautiful": true,
"data": 123,
"keywords": ["Rhine", "River"]
},
{
"id": 1,
"name": "Zurich",
"founded": 0,
"beautiful": false,
"data": "no",
"keywords": ["Limmat", "Lake"]
}
]
};

let jsonConvert: JsonConvert = new JsonConvert();
jsonConvert.operationMode = OperationMode.LOGGING;
jsonConvert.ignorePrimitiveChecks = false;
jsonConvert.valueCheckingMode = ValueCheckingMode.DISALLOW_NULL;

let country: Country;
try {
  country = jsonConvert.deserialize(jsonObject, Country);
  country.cities[0].printInfo();
} catch (e) {
  console.log((<Error>e));
}

}

}

****************** package.json ********************
{
"name": "demo-json2typescript",
"version": "0.0.1",
"author": "Ionic Framework",
"homepage": "https://ionicframework.com/",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/common": "^7.2.2",
"@angular/core": "^7.2.2",
"@angular/forms": "^7.2.2",
"@angular/http": "^7.2.2",
"@angular/platform-browser": "^7.2.2",
"@angular/platform-browser-dynamic": "^7.2.2",
"@angular/router": "^7.2.2",
"@ionic-native/core": "^5.0.0",
"@ionic-native/splash-screen": "^5.0.0",
"@ionic-native/status-bar": "^5.0.0",
"@ionic/angular": "^4.1.0",
"core-js": "^2.5.4",
"json2typescript": "^1.2.0",
"rxjs": "~6.5.1",
"tslib": "^1.9.0",
"zone.js": "~0.8.29"
},
"devDependencies": {
"@angular-devkit/architect": "~0.13.8",
"@angular-devkit/build-angular": "~0.13.8",
"@angular-devkit/core": "~7.3.8",
"@angular-devkit/schematics": "~7.3.8",
"@angular/cli": "~7.3.8",
"@angular/compiler": "~7.2.2",
"@angular/compiler-cli": "~7.2.2",
"@angular/language-service": "~7.2.2",
"@ionic/angular-toolkit": "~1.5.1",
"@types/node": "~10.14.2",
"@types/jasmine": "~2.8.8",
"@types/jasminewd2": "~2.0.3",
"codelyzer": "~4.5.0",
"jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~4.1.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-jasmine": "~1.1.2",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.4.0",
"ts-node": "~8.1.0",
"tslint": "~5.16.0",
"typescript": "~3.1.6"
},
"description": "An Ionic project"
}

************************ tsconfig.json ************************
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"module": "es2015",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
]
}
}

THANKS!!!

@andreas-aeschlimann
Copy link
Member

Hi, I'm sorry but it's actually an issue of the ReadMe file. We have changed the method signatures to be more strict a while ago, that's why you are seeing an error here.

Let's try to understand your actual error here:

Type 'Country | Country[]' is not assignable to type 'Country'.\n Type 'Country[]' is missing the following properties from type 'Country': name, cities – startLineNumber: 61

If you are going to line 61, you will see:

59  let country: Country;
60  try {
61      country = jsonConvert.deserialize(jsonObject, Country);
62      country.cities[0].printInfo();
63  } catch (e) {
64      console.log((<Error>e));
65  }

So your problem is that the method you are calling – deserialize() – returns the type Country | Country[], while your variable country only has type Country.

We now have two possibilities to fix it:

  1. Change line 59 to let country: Country | Country[].

  2. Because we know that our json object is actually a plain object and NOT an array, we know the result should be object. We can adjust line 61 to country = jsonConvert.deserializeObject(jsonObject, Country);.

I would prefer solution 2, because it would throw an error if your json was not the expected object, but an array. If you use solution 1, you will never know in your code whether the result will be a Country object or array. Also, json2typescript will not throw an error if it's not the one you expect.

@andreas-aeschlimann andreas-aeschlimann self-assigned this May 4, 2019
@andreas-aeschlimann andreas-aeschlimann added the invalid This doesn't seem right label May 4, 2019
@ThawedBuffalo
Copy link
Author

Thank you Andreas- not only for your quick response, but also for the manner in which you responded. You explained the resolution which was quite obvious in an informative and professional way. Thank you for helping me as this was the first time I ever posted on an issue. I appreciate your help. Problem solved!

Jim

@andreas-aeschlimann
Copy link
Member

andreas-aeschlimann commented May 4, 2019

No worries and good luck with your project!

EDIT: The documentation has been updated and a new version is checked in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
invalid This doesn't seem right
Projects
None yet
Development

No branches or pull requests

2 participants