johnweisz / typedjson Goto Github PK
View Code? Open in Web Editor NEWTyped JSON parsing and serializing for TypeScript that preserves type information.
License: MIT License
Typed JSON parsing and serializing for TypeScript that preserves type information.
License: MIT License
ERROR in [default] node_modules/typedjson/src/typed-json.ts:51:4
Left-hand side of assignment expression cannot be a constant or a read-only property.
ERROR in [default] node_modules/typedjson/src/typed-json.ts:234:36
Property 'prototype' does not exist on type 'never'.
ERROR in [default] node_modules/typedjson/src/typed-json.ts:456:12
Unreachable code detected.
JsonObject does not accept a class with a parameterized constructor as a known type.
@JsonObject
class Person {
@JsonMember firstName: string;
@JsonMember lastName: string;
constructor(firstName: string, lastName: string) {
this.firstName = firstName;
this.lastName = lastName;
}
}
@JsonObject({
knownTypes: [Person] // Error: type 'Person' is not assignable to type 'new () => any'.
})
class Company { }
I have an issue when trying to use the library in my code.
Basically when I access the first page in the browser I get a (SystemJS) expected expression, got '<'
I think it mast be an incorrect way I declare things in the systemjs.conf.js.
If you could help me in the right direction it would be great.
Here goes part of the code.
thanks
systemjs.conf.js
map['typedjson/js'] = 'node_modules/typedjson/js';
packages['typeddjson/js'] = { main: 'index.js', defaultExtension: 'js' };
person.ts
import {JsonObject, JsonMember} from 'typedjson/js';
@JsonObject
export class Person {
@JsonMember
name:string;
@JsonMember
surname:string;
@JsonMember
age:Number;
public getFullDescription() {
return this.name + " " + this.surname + " " + this.age;
}
}
MapUtilsTest
import {TypedJSON} from 'typedjson/js';
import {Person} from "./person";
export class MapUtilsTest {
public static testPerson(): Person {
let json = PersonDataFixtures.getPerson();
let jsonStr = JSON.stringify(json);
const person = TypedJSON.parse(jsonStr, Person);
this.print('person');
this.print(jsonStr);
this.print(person.getFullDescription());
return person;
}
Hello,
I'm facing this problem:
If I export a @JsonObject Class (let's say Person) that has annotated property "address" of type Address (which is also a @JsonObject), I get an error:
'type' of 'Person.address' is undefined.
Unless I export the Address class before Person.
That's not a problem when dealing with a few model classes but really a big issue, or something the developer should not be responsible for, in larger projects.
Am I missing something?
Thank you in advance.
If type
doesn't have JsonObjectMetadata
, TypedJSON.parse
fall to JSON.parse
with argument class of type
constructor as reviver.
From typed-json.ts
...
var TypedJSON: TypedJSON = {
...
parse: function (json: string, type?: any, settings?: SerializerSettings): any {
if (JsonObjectMetadata.getFromType(type)) {
return Deserializer.readObject(json, type, Helpers.merge(configSettings, settings || {}));
} else {
return JSON.parse.apply(JSON, arguments);
}
}
};
As result of parse we have undefined or default value depend on type
and/or json
string.
i.e.
let x = TypedJSON.parse<Number>("10", Number);
Possible solutions are call JSON.parse
only with json
string or take reviver from SerializerSettings.
return JSON.parse.apply(JSON, json);
or
return JSON.parse.apply(JSON, [json, settings && settings.reviver]);
Hello,
Here is another error with TypedJSON while using [email protected]
ERROR in [default] /Users/xxxxx/web-app/node_modules/typedjson/src/typed-json.ts:242:36 Property 'prototype' does not exist on type 'never'.
It would be awesome if TypedJSON could be used without requiring a module-loading system. If this is considered, the code should be made compatible for global use, for example by including fake AMD fallback functionality that is a wrapper for global injection. This would be accompanied by global type-definitions as well.
This would allow using TypedJSON with namespace syntax, bypassing the requirement of a module-loading system:
@TypedJSON.JsonObject
class Person {
@TypedJSON.JsonMember
firstName: string;
@TypedJSON.JsonMember
lastName: string;
}
var john = TypedJSON.TypedJSON.parse('{ "firstName": "John", "lastName": "Doe" }', Person);
The double TypedJSON is a bit meh, but this would be a secondary, fallback functionality. The preferred way of importing TypedJSON is the ES6 syntax anyways, which is inherently accompanied by a module loading system.
Hi, I'm trying to use TypedJSON to deserialize a dictionary structure. I'm also using an Aurelia CLI project, which means I'm not using the reflect-metadata polyfill as that currently breaks the @observable decorator functionality in the Aurelia framework (issue here), so I'm manually specifying the type for each JsonMember, but don't know how to do this with a dictionary type as there is no obvious constructor function, for example:
ModelValidationResults.ts
import { ValidationMessage } from "./ValidationMessage";
import { JsonMember, JsonObject } from "typedjson-npm";
@JsonObject
export class ModelValidationResults {
@JsonMember
errors: { [id: string]: ValidationMessage[] };
@JsonMember
warnings: { [id: string]: ValidationMessage[] };
}
ValidationMessage.ts
import { JsonMember, JsonObject } from "typedjson-npm";
@JsonObject
export class ValidationMessage {
@JsonMember({ type: String })
key: string;
@JsonMember({ type: String })
description: string;
}
Basically I have no idea what to use as the type
setting for the errors
or warnings
members, or if TypedJSON supports what I'm trying to do. Can you provide any guidance on this scenario?
If I was to implement say a Dictionary<T>
class, then I could use that as my type, would that work with TypedJSON as well?
Any help appreciated!
Thanks,
Sam
Currently, custom serialization and deserialization only kicks in if JSON root is a JsonObject class. If the root object is an array, TypedJSON won't create the correct class instances, even when type-hints are present.
Hello,
I have a problem with a custom serialization.
I have the following code:
@JsonObject({ initializer: Entity.fromJson, serializer: Entity.toJson })
export class Entity {
static fromJson(json: any): Entity {
//deserialization to Entity object
}
static toJson(entity: Entity): any {
//serialization from Entity to json.
}
constructor() { }
//class properties
//..
}
Deserialization is performed without any problems, but during serialization the method toJson isn't called. I've debugged TypedJson source code a bit, and found that in these lines:
//object is Entity here
objectMetadata = JsonObjectMetadata.getFromInstance(object);
if (objectMetadata && typeof objectMetadata.serializer === "function") {
json = objectMetadata.serializer(object);
}
objectMetadata doesn't contain serializer property at all.
I suppose the problem can be in this function
function JsonObject(optionsOrTarget) {
var options;
if (typeof optionsOrTarget === "function") {
options = {};
}
//the rest of code
}
It contains initializing of initializer property:
if (typeof initializer === "function") {
objectMetadata.initializer = initializer;
}
But luck of any serializer property initializing.
But it is only my speculations and I can be wrong.
Currently, nested arrays are serialized by adding a type-hint to every object-element, which can then be read to determine correct types. However, this is inconvenient when the JSON is coming from an external source not produced by TypedJSON.
Proposal is to create a nestable JsonMember options structure in a backwards compatible way:
interface JsonMemberOptions {
elementType?: JsonMemberOptions | Function;
// ...
}
Proposed usage:
@JsonObject
class 2DGrid {
@JsonMember({
elementType: {
type: Array,
elementType: Number
}
})
gridPoints: Array<Array<number>>;
}
This provides a means to defining runtime-readable type information for infinitely nested array types at the cost of significantly increased verbosity in these cases of the otherwise clean syntax of TypedJSON. This will also effectively turn current syntax into an alias:
@JsonMember({ elementType: Array })
Is now effectively an alias for:
@JsonMember({ elementType: { type: Array } })
Taking this into consideration, 'elementType' might be considered being deprecated in favor of an option name more closely hinting at the new functionality, like 'elements'.
@JsonMember({ elements: Array })
@JsonMember({ elements: { type: Array } })
When using Webpack to package the Ng2 projects with TypeScript, got such error outputs in console.
ERROR in ./~/typedjson/js/tests/polymorphism-abstract-class.js
Module not found: Error: Cannot resolve 'file' or 'directory' ../typed-json in E:\Developments\Projects\fenxiao\node_modules\typedjson\js\tests
@ ./~/typedjson/js/tests/polymorphism-abstract-class.js 20:8-84
ERROR in ./~/typedjson/js/tests/polymorphism-custom-names.js
Module not found: Error: Cannot resolve 'file' or 'directory' ../typed-json in E:\Developments\Projects\fenxiao\node_modules\typedjson\js\tests
@ ./~/typedjson/js/tests/polymorphism-custom-names.js 20:8-84
ERROR in ./~/typedjson/js/tests/polymorphism-interface.js
Module not found: Error: Cannot resolve 'file' or 'directory' ../typed-json in E:\Developments\Projects\fenxiao\node_modules\typedjson\js\tests
@ ./~/typedjson/js/tests/polymorphism-interface.js 15:8-84
ERROR in ./~/typedjson/js/tests/polymorphism-nested-arrays.js
Module not found: Error: Cannot resolve 'file' or 'directory' ../typed-json in E:\Developments\Projects\fenxiao\node_modules\typedjson\js\tests
@ ./~/typedjson/js/tests/polymorphism-nested-arrays.js 20:8-84
ERROR in ./~/typedjson/js/tests/polymorphism.js
Module not found: Error: Cannot resolve 'file' or 'directory' ../typed-json in E:\Developments\Projects\fenxiao\node_modules\typedjson\js\tests
@ ./~/typedjson/js/tests/polymorphism.js 20:8-84
ERROR in ./~/typedjson/js/tests/single-class.js
Module not found: Error: Cannot resolve 'file' or 'directory' ../typed-json in E:\Developments\Projects\fenxiao\node_modules\typedjson\js\tests
@ ./~/typedjson/js/tests/single-class.js 15:8-64
Do I need to set an exclude config or something I missed?
Thanks.
I cannot find how I can parse an array of instances of a known class. This frequently occurs when parsing the response of a REST service.
Overview
Remaining issues:
Fixed:
Notes
Specifying an abstract class as the root type of a JSON object is a practical use scenario. Currently the type signature of TypedJSON.parse
does not allow it:
parse<T>(text: string, type: { new (): T }): T;
Enabling abstract classes to be specified as type
would be possible with the following overload signature (besides accepting any
):
parse<T>(text: string, type: Function): T;
... which would however also effectively lift the requirement of parameterless constructors. As such, this issue will remain open until a suitable solution is found.
I've done it here: https://github.com/davidstellini/TypedJSON
Hi,
If dealing with multiple decorators on an entity class, it seems @JsonObject needs to be the very next to the class declaration. Otherwise the metadata is somehow mixed up and isExplicitlyMarked evals to false.
@JsonObject @MyEntityDecorator export class MyEntity { @JsonMember public readonly name: String; }
Above will be parsed to a normal JSON, not MyEntity! That feels is a bit contra intuitiv to me. If the order of decorators is changed, everything works as expected.
This is true at least for [email protected]
Cheers
Currently, serializing then deserializing an object where multiple properties reference the same object will yield separate objects:
@JsonObject
class Person { }
@JsonObject
class Company {
@JsonMember boss: Person;
@JsonMember owner: Person;
}
var company = new Company();
company.boss = company.owner = new Person();
var ripoff = TypedJSON.parse(TypedJSON.stringify(company), Company);
ripoff.boss === ripoff.owner; // false
This feature is planned to be supported in the future.
Hi,
I am using webpack, ng2, ... (https://github.com/AngularClass/angular2-webpack-starter)
My application is working fine.
I am facing an issue with TypedJSON
when classes are not in the same .ts
file.
Uncaught Error: No valid 'elements' option was specified for 'OrderDetail.trades'.
order.ts
import { Trade } from './trade';
@JsonObject({ knownTypes: [Trade] })
export class OrderDetail {
@JsonMember({ elements: Trade }) trades: Array<Trade>;
}
trade.ts
@JsonObject
export class Trade {
@JsonMember id: string;
}
If I put the class Trade
in the same file where is OrderDetail
, it is working fine.
Hello,
I just used TypedJSON in a new project using another release of webpack and i ran exactly into this issue:
http://stackoverflow.com/questions/38392697/webpack-umd-critical-dependency-cannot-be-statically-extracted
Here are my webpack node packages:
...
"webpack": "2.1.0-beta.22",
"webpack-dev-middleware": "^1.6.1",
"webpack-dev-server": "^2.1.0-beta.2",
"webpack-md5-hash": "^0.0.5",
"webpack-merge": "^0.14.1",
....
To fix it, i compiled the typed-json.ts
with this property and it resolved my issue.
When returning a derived type from a @JsonObject
initilizer function, the generic type parameter must be specified to match the decorated class:
@JsonObject
class Foo { }
@JsonObject<Bar>({
initializer: (json) => {
return new Baz();
}
})
class Bar extends Foo { }
@JsonObject
class Baz extends Bar { }
If not explicitly defined, the compiler will allow returning a base type instead of a derived type. The issue is caused by the TypeScript compiler itself: when inferring generic type, the return type of the initializer
function takes precedence over the instance type.
Related question: http://stackoverflow.com/q/36835363/2788872
Properties with string literal types are serialized and deserialized as Object
. This is caused by the Typescript compiler, which emits incorrect metadata information for these types. See microsoft/TypeScript#10809
For example, the following code will produce incorrect behavior if ReflectDecorators is used to automatically detect types:
@JsonObject
class Person {
@JsonMember
public name: "John" | "James";
}
The solution, until this is fixed by the TypeScript team, is to manually define the type
setting:
@JsonObject
class Person {
@JsonMember({ type: String })
public name: "John" | "James";
}
This will raise a warning in the console however, indicating that the specified type does not match detected type:
@JsonMember: 'type' specified for 'Person.name' does not match detected type.
Since this otherwise potentially helpful warning only occurrs temporarily until the fix is shipped by Microsoft, no action will be done to suppress it in these cases.
Currently, whether or not a type-hint should be emitted is determined by the following conditional statement:
if (settings.requireTypeHints || (object.constructor !== settings.objectType && settings.enableTypeHints)) {
json[settings.typeHintPropertyKey] = JsonObjectMetadata.getKnownTypeNameFromInstance(object);
}
Which will emit type-hint information in some required cases (like nested arrays as of 0.1.4), even if type-hinting is explicitly disabled. The line needs to be rewritten to:
if (settings.enableTypeHints && (settings.requireTypeHints || object.constructor !== settings.objectType)) {
json[settings.typeHintPropertyKey] = JsonObjectMetadata.getKnownTypeNameFromInstance(object);
}
Binary values cannot be automatically converted to and from JSON natively, and neither does TypedJSON implement special serialization logic for them as it does for Date, for example. This is currently only possible by defining custom serialization procedures, or using getters/setters that transform to and from a string.
The proposal is to introduce this feature through Base64 encoding, which is also used by other JSON-serializers in other languages. Some popular native Javascript data types would receive automatic support for encoding binary data:
*This might be tricky. A Blob could be easily serialized by converting it to an ArrayBuffer and then to Base64, but that requires the FileReader API, which is asynchronous. This would require a previously planned, although yet to be announced feature: asynchronous serialization and deserialization.
Generating simple JSON schemas could be a fairly trivial task given the metadata structure that is created when annotating with JsonObject
and JsonMember
. Considering that and the possible usefulness of this feature, this is planned to be soon available.
However, validating JSON against these schemas will not be an explicit feature of TypedJSON, as most aspects (like types and required properties) are already validated in the deserialization process itself.
Currently, when deserializing invalid JSON, error messages are not helpful. For example:
Expected value to be of type 'Array', got 'Number'.
The error does not tell which object and property it is about, which makes it hard and frustrating to track down the exact issue. Error messages should clearly indicate an unambiguous identifier of the property with the incorrect datatype, for example:
Expected 'Person.firstName' to be of type 'String', got 'Number'.
Hi,
Can you please provide an example for using typeResolver? (Typescript please)
Thanks
I'm trying to use TypedJSON
in ionic2
project, this is the way that I'm trying to import
import { TypedJSON } from 'typedjson';
But i get the following error
/myproject/node_modules/typedjson/js/index.js does not export TypedJSON (imported by /myproject/src/pages/mymodule/mymodule.ts)
how can I fix it?
A property with an interface as its type will be detected as of type Object
by reflect-metadata. Also, an interface cannot be specified as type
or elementType
in JsonMember settings.
interface Point {
x: number;
y: number;
}
class Graph {
@JsonMember // reflect-metadata will detect type 'Object'.
root: Point;
}
If a primitive is expected during deserialization, value assignment is done without checking if the source value is indeed of the correct type.
When @JsonMember
is applied to a getter/setter, even when using reflect-metadata the type
setting must be specified or a type-annotation must be added:
@JsonObject
class Foo {
@JsonMember({ type: String })
public get foo() { return "foo"; }
public set foo(value) { }
@JsonMember
public get foo(): string { return "foo"; }
public set foo(value: string) { }
}
This issue originates from the TypeScript compiler, type information is not emitted correctly when type inference occurs.
It's not working with the defined @JsonMembers of the parent class.
Is there any options to be able to use the defined members of the parents class?
Best regards
Dominic
Many thanks for TypedJSON.
Why is the elements option required for arrays when typeHints
are in use? If I change warnArray = true
and annotate with knownTypes
everything works fine.
Hi, first of all thanks for this awesome package! It is really useful and allows to use full power of TypeScript without much hassle. ๐
Unfortunately, there are some build warnings when you import the package via NPM and load it with Webpack. This is related to #24 . After following the steps there I've managed to hide most of the errors and warnings by excluding the /tests/ folder from Webpack. This is not a big problem. But there are two errors that are left after doing so:
[0] WARNING in ./~/typedjson/js/index.js
[0] Critical dependencies:
[0] 25:24-31 require function is used in a way in which dependencies cannot be statically extracted
[0] @ ./~/typedjson/js/index.js 25:24-31
[0]
[0] WARNING in ./~/typedjson/js/index.d.ts
[0] Module parse failed: C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\typedjson\js\index.d.ts The keyword 'interface' is reserved (23:0)
[0] You may need an appropriate loader to handle this file type.
[0] SyntaxError: The keyword 'interface' is reserved (23:0)
[0] at Parser.pp$4.raise (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\acorn\dist\acorn.js:2221:15)
[0] at Parser.pp$3.parseIdent (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\acorn\dist\acorn.js:2182:14)
[0] at Parser.pp$3.parseExprAtom (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\acorn\dist\acorn.js:1774:21)
[0] at Parser.pp$3.parseExprSubscripts (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\acorn\dist\acorn.js:1715:21)
[0] at Parser.pp$3.parseMaybeUnary (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\acorn\dist\acorn.js:1692:19)
[0] at Parser.pp$3.parseExprOps (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\acorn\dist\acorn.js:1637:21)
[0] at Parser.pp$3.parseMaybeConditional (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\acorn\dist\acorn.js:1620:21)
[0] at Parser.pp$3.parseMaybeAssign (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\acorn\dist\acorn.js:1597:21)
[0] at Parser.pp$3.parseExpression (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\acorn\dist\acorn.js:1573:21)
[0] at Parser.pp$1.parseStatement (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\acorn\dist\acorn.js:727:47)
[0] at Parser.pp$1.parseTopLevel (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\acorn\dist\acorn.js:638:25)
[0] at Parser.parse (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\acorn\dist\acorn.js:516:17)
[0] at Object.parse (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\acorn\dist\acorn.js:3098:39)
[0] at Parser.parse (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\webpack\lib\Parser.js:902:15)
[0] at DependenciesBlock.<anonymous> (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\webpack\lib\NormalModule.js:104:16)
[0] at DependenciesBlock.onModuleBuild (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\webpack-core\lib\NormalModuleMixin.js:310:10)
[0] at nextLoader (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\webpack-core\lib\NormalModuleMixin.js:275:25)
[0] at C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\webpack-core\lib\NormalModuleMixin.js:259:5
[0] at Storage.provide (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:52:20)
[0] at CachedInputFileSystem.readFile (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:140:24)
[0] at DependenciesBlock.onLoadPitchDone (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\webpack-core\lib\NormalModuleMixin.js:255:7)
[0] at DependenciesBlock.loadPitch (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\webpack-core\lib\NormalModuleMixin.js:182:27)
[0] at DependenciesBlock.doBuild (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\webpack-core\lib\NormalModuleMixin.js:241:4)
[0] at DependenciesBlock.build (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\webpack\lib\NormalModule.js:84:14)
[0] at Compilation.buildModule (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\webpack\lib\Compilation.js:126:9)
[0] at C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\webpack\lib\Compilation.js:309:10
[0] at C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\webpack\lib\NormalModuleFactory.js:58:13
[0] at NormalModuleFactory.applyPluginsAsyncWaterfall (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\tapable\lib\Tapable.js:75:69)
[0] at onDoneResolving (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\webpack\lib\NormalModuleFactory.js:38:11)
[0] at onDoneResolving (C:\Code\aft\aft-seed-integration\accsoft-aft-server\src\resources\node_modules\webpack\lib\NormalModuleFactory.js:121:6)
[0] @ ./~/typedjson/js ^\.\/.*$
Later I found out that I should import directly TS files instead of JS. I've tried to change the imports to proper ones, but there is one problem. You are allowing the usage of implicit any, whereas we don't. Therefore including TS code instead of JS code causes to show even more errors in the console. AFAIK so far there is no other solution than to switch off the 'implicit any' check for our TSC.
I'd like to ask - are you planning to do something about this? It would be very nice to have a way to include this package without having warnings and without having to turn off 'implicit any' check for the whole project. The easiest solution would be I guess to modify the code and switch on the 'implicit any' check in your package. However you're the only one that can do it if we want to import this package via NPM. Are you willing to fix that or maybe accept a pull request? I'd be happy to help if you don't have time to do so. ๐ If anyone has some other solution, please let me know here.
Hi, Really love what you done here that why I would like to use it both client and server in isomorphic way
Anyway there are some issues warning report from Webpack bundle cause by importing module
WARNING in ./
/typedjson/js/index.js/typedjson/js/index.js 25:24-31
Critical dependencies:
25:24-31 require function is used in a way in which dependencies cannot be statically extracted
@ ./WARNING in ./~/typedjson/js/index.d.ts
Module parse failed: C:\Users\U6038377\Documents\ReadAround.me-Isomorphic\node_modules\typedjson\js\index.d.ts The keywo
rd 'interface' is reserved (23:0)
You may need an appropriate loader to handle this file type.
SyntaxError: The keyword 'interface' is reserved (23:0)
so I need to do a tricky module import like this to remove all warning and error from both side
if (process.env.BROWSER) { // wepback
JsonObject = require('typedjson/src/typed-json.ts').JsonObject;
JsonMember = require('typedjson/src/typed-json.ts').JsonMember;
}else { // Node with ts-node/register
JsonObject = require('typedjson').JsonObject;
JsonMember = require('typedjson').JsonMember;
}
Any idea for this problem ?
Thank for help !
TypedJSON.parse
when called without a type supplied will instantiate a JSON object into a regular Javascript object (Object
instance). Therefore due to the potentially misleading 'Typed' part in the call instruction, this might cause some headache when the 'type' parameter is accidentally omitted, and JSON is deserialized into Object
instance.
Consider the following example, where the second argument of TypedJSON.parse is accidentally omitted. It's certainly misleading:
var person: Person = TypedJSON.parse(json);
person instanceof Person; // false
It's possible this would result in standard JSON functions (those having nothing to do with typed serialization and deserialization) being stripped from TypedJSON in the future (preceded with a deprecation warning).
Currently, an abstract class cannot be specified as the root type of deserialization, but that functionality is otherwise a practical use scenario. Currently the type signature of TypedJSON.parse
does not allow it:
parse<T>(text: string, type: { new (): T }): T;
Enabling abstract classes to be specified as type
would be possible with the following overload signature (besides accepting any
):
parse<T>(text: string, type: Function): T;
... which would however also effectively lift the requirement of parameterless constructors. A workaround solution is being investigated. To summarize, a type signature is needed that accepts either:
new (): T
), orHi John,
It is not really important but i saw the version number in package.json
is "v0.1.5" but is also "0.2.0" in the source file.
Just to let you know. (I was a little bit lost when i compared map files with my package.json
while debugging)
It seems from the tests that members of Date type should be automatically deserialized without type hint. However, it didn't deserialize as Date but Object which turns out be something like
new Object('2016-07-29')
Without type hint: deserialize as object
@JsonObject
export class Team {
@JsonMember
public createdAt: Date;
}
let json = { createdAt: '2016-07-29' };
let str = JSON.stringify(json);
TypedJSON.parse(str, Team);
With type hint: deserialize as Date
@JsonObject
export class Team {
@JsonMember({ type: Date })
public createdAt: Date;
}
When deserializing nested arrays, only primitives can be accurately instantiated. All other non-null values will be instantiated to Object
instances, except when type-hints are present and enabled.
Custom types in nested arrays would require an elementType
setting for @JsonMember
that is nestable -- which is a planned feature, but not currently supported.
Multi-frame support is currently sketchy at best. In the meantime, serialization and deserialization should be performed in the same frame the serializable classes are defined, and such classes should not reference types defined in other frames.
Hi there,
when using "target": "es6"
option in tsconfig.json
I get following error:
../deps/typed-json/src/typed-json.ts(51,5): error TS2322: Type '{ parse: (sJSON: string) => any; stringify: (value: any) => any; }' is not assignable to type 'JSON'.
Property '[Symbol.toStringTag]' is missing in type '{ parse: (sJSON: string) => any; stringify: (value: any) => any; }'.
We get this error because JSON[Symbol.toStringTag]
is missing.
Following code seems to work (around L50):
if (!JSON) {
JSON = {
[Symbol.toStringTag]: 'JSON',
...
Thanks for your work.
It's only possible to parse from JSON but sometimes (like in express application with activated bodyParser) it could be helpful to have the opportunity to parse to a typed object from a objectwhich was already parsed by JSON.parse.
The simple @JsonMember
doesn't work, I have error "No valid 'type' option was specified for 'DatabaseConfig.password'"
. I have to use:
@JsonMember({ type: String })
firstName: string;
In my package.json
:
"dependencies": {
"reflect-helper": "^1.0.2",
"reflect-metadata": "^0.1.8",
},
In my tsconfig.json
:
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
}
What else I have to do to make it work like in sample?
@JsonObject
class Person {
@JsonMember
firstName: string;
@JsonMember
lastName: string;
public getFullname() {
return this.firstName + " " + this.lastName;
}
}
Wrapper objects for primitive types are not preserved when serializing. For example, String
becomes the primitive string
, Number
becomes the primitive number
.
With reflect-metadata, the TypeScript compiler emits the same metadata information for both primitives and wrapped values, which makes it impossible to distinguish between the two. When manually specifying types, a primitive cannot be passed as a type
setting for a JsonMember
.
A theoretical solution to this problem would be adding an optional isPrimitive
setting to @JsonMember
, but such functionality seems to be entirely useless. As such, this feature is not scheduled to be added anytime soon.
I would like to generate a well formated json file, instead of a long json string without any space and enter. However, seems no way to achieve it without modifying the source. In the typedjson/js/index.js, it has JSON.stringify call:
return JSON.stringify(this.writeToJsonObject(object, {
738 objectType: ObjectType,
739 enableTypeHints: settings.enableTypeHints,
740 typeHintPropertyKey: settings.typeHintPropertyKey
741 }), settings.replacer);
hope to pass the space as the 3rd parameter, like the following:
741 }), settings.replacer, 4);
so that it can generate well-formated json file.
Hello,
I just upgraded my projet to Angular2-RC6 and Typescript 2.0.
Everything works fine excepted TypedJSON now returns classic objects instead of my defined classes. It might come from Typescript 2.0.
Any clue ?
Hi, hopefully this is a quick and easy question - what should the type setting be when the member type is an enum? Enums don't have a constructor function as far as I can see so this code won't work:
ObjectState.ts
export enum ObjectState {
Unchanged = 0,
Added = 1,
Modified = 2,
Deleted = 3
}
Entity
import { ObjectState } from "./ObjectState";
import { JsonMember, JsonObject } from "typedjson-npm";
@JsonObject
export class Entity {
@JsonMember({ type: ObjectState }) // won't compile
objectState: ObjectState;
}
Should I just use Number? Or is there a better pattern to use?
Thanks!
Sam
Can this be used to deserialize a JSON object to a Map<K,V> object? What kind of annotation would be needed?
If members of a class are deserialized without being serialized first, ordering is effectively ignored.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.