GillianPerard / typescript-json-serializer

A typescript library to deserialize json into typescript classes and serialize classes into json.
MIT License
212 stars 29 forks source link

[BUG]: cryptic errors making hard to debug cycle or someething #232

Open deanbiltup opened 2 hours ago

deanbiltup commented 2 hours ago

Version

6.0.0

Description

I suspect a cycle but can't find it. In guice, on errors, it would report the cycle, A, B, C, A so you could fix. Perhaps this is a feature request though I think it is more a usability bug costing time every time we hit it. if you have a debug process that would be amazing. I changed my entity to this code adding {type: ProposalDto} and things broke :( ....

@JsonObject()
export class FetchProposalsResponse {
    @JsonProperty({ type: ProposalDto })
    public proposals?: ProposalDto[]
    @JsonProperty()
    public hasMoreData?: boolean
    @JsonProperty()
    public totalSize?: number;
}

Error

The error is very very cryptic though so I can't even tell how deep we are 

Navigation error: TypeError: Cannot read properties of undefined (reading 'name')
    at f2.deserializeProperty (index.esm.js:1:7351)
    at index.esm.js:1:2749
    at Array.forEach (<anonymous>)
    at f2.deserializeObject (index.esm.js:1:2713)
    at f2.deserializeProperty (index.esm.js:1:7398)
    at index.esm.js:1:2749
    at Array.forEach (<anonymous>)
    at f2.deserializeObject (index.esm.js:1:2713)
    at index.esm.js:1:8725
    at Array.reduce (<anonymous>)


### Reproduction

I am currently 2 hours into debugging this one so far.   I have no idea as our APIs have grown to be very large and picking them apart to simplify is near impossible breaking at each step.   This is the second time we got into this stage and it takes a super long time to debug(at least 2-8 hours) were normally, we are closing a jira ticket per hour so it results in us missing 2-8 jira tickets when we get this error. 

### On which OS the bug appears?

macOS

### What is your project type?

angular

### On which build mode the bug appears?

development but maybe both

### Anything else?

I am guessing somewhere in the library, there is a variable.name.  Perhaps a 'if(!variable) throw Error("more detail") can be added which would then make this super simple to debug... at the very least, can it throw error with info on the current type that is being processed like XXXDto seems to not have xxx defined perhaps due to cycle.
deanbiltup commented 2 hours ago

NOTE: by the way, the lib has been super solid!!!!!!! thanks!!! All our apis are used by the angular client and by the server so our apis are 100% the same now so developers can easily read the contracts on either end since it is the same file for both server developer and GUI developer (though we are all full stack anyways).

deanbiltup commented 1 hour ago

Ok, I tried deleting entire app to just focus on the api but that became a rabbit hole :( . full object heirarchy is

@JsonObject()
export class FetchProposalsResponse {
    //@JsonProperty({ type: ProposalDto })
    @JsonProperty()
    public proposals?: ProposalDto[]
    @JsonProperty()
    public hasMoreData?: boolean
    @JsonProperty()
    public totalSize?: number;
}

@JsonObject()
export class ProposalDto {
    @JsonProperty()
    public outline?: OutlineDto;

    //loaded for customer view only
    @JsonProperty({ type: TrainerXrefDto })
    public potentialTrainers?: TrainerXrefDto[]
    //loaded for trainer view only..
    @JsonProperty()
    public customer?: CustomerDto
}

/************************************
 This should be 1 to 1 with CustomerProposedOutlineDbo
 while OutlineVersionDto is 1 to 1 with OutlineVersionDbo
 (in case they vary, we do not want to confuse the two)
 ******************************/
@JsonObject()
export class OutlineDto {
    @JsonProperty()
    public outlineId?: string;
    @JsonProperty()
    public title?: string;
    @JsonProperty()
    public gptVersion?: string;
    //fully processed and ready to display outline...
    @JsonProperty()
    public html?: string;
    //original original with special ж, ф, and я characters inside
    @JsonProperty()
    public markdown?: string;
    @JsonProperty()
    public durationHours?: number;
    @JsonProperty()
    public availableStart?: Date;
    @JsonProperty()
    public availableEnd?: Date;

    @JsonProperty({
        beforeDeserialize: stringToClassType,
        afterSerialize: classTypeToString
    })
    public trainingType?: ClassTypeEnumDto;
    @JsonProperty({
        beforeDeserialize: stringToClassSize,
        afterSerialize: classSizeToString
    })
    public numberOfStudents?: ClassSizeEnumDto;
    @JsonProperty()
    public description?: string;
    @JsonProperty()
    public prerequisites?: string[];
    @JsonProperty()
    public learningObjectives?: string[];
    @JsonProperty()
    public assistantVersionDbId?: string;

    @JsonProperty()
    public stage?: string;

    @JsonProperty()
    public created?: Date;

}

@JsonObject()
export class TrainerXrefDto {
    @JsonProperty()
    public trainer?: TrainerDto;

    //TODO(dhiller): FIX to be the enum instead
    @JsonProperty()
    public stage?: string;

    @JsonProperty()
    public trainerXrefId?: string;
}

@JsonObject()
export class TrainerDto {
    @JsonProperty()
    public trainerId?: string;
    @JsonProperty()
    public commonData? = new CommonUserDataDto();
    @JsonProperty()
    public accessToken?: string;
    @JsonProperty()
    public roles?: string[];
    @JsonProperty()
    public hourlyRate?: number;
    @JsonProperty()
    public dailyRate?: number;
    @JsonProperty()
    public halfDayRate?: number;
    @JsonProperty()
    public username?: string;
    @JsonProperty()
    public about?: string;
    @JsonProperty()
    public linkedInUrl?: string;
    @JsonProperty()
    public githubUrl?: string;
    @JsonProperty({ type: SkillDto })
    public skills?: SkillDto[];
    @JsonProperty()
    public profileState?: ProfileState = ProfileState.UNSUBMITTED;
    @JsonProperty()
    public rating?: number;
}

@JsonObject()
export class CommonUserDataDto {
    @JsonProperty()
    //probably should merge with MemberDto
    public dbUid?: string;
    @JsonProperty()
    public firstName?: string;
    @JsonProperty()
    public lastName?: string;
    @JsonProperty()
    public email?: string;
    @JsonProperty()
    public avatar?: string;
    @JsonProperty()
    public status?: string;
    @JsonProperty()
    public title?: string;
    @JsonProperty()
    public company?: string;
    @JsonProperty()
    public phone?: string;
}

@JsonObject()
export class SkillDto {
    @JsonProperty()
    public skillId?: string;
    @JsonProperty()
    public name?: string;
}

@JsonObject()
export class CustomerDto {
    public customerId?: string;
    @JsonProperty()
    public commonData? = new CommonUserDataDto();
    public roles?: string[];
}
GillianPerard commented 1 hour ago

Hi, let me check, but could you provide the payload you try to deserialize so that I can check with real data?