JohnWeisz / TypedJSON

Typed JSON parsing and serializing for TypeScript that preserves type information.
MIT License
603 stars 64 forks source link

Be able to use @jsonMapMember(K,V) where V is an array. #127

Open Jakartoine opened 4 years ago

Jakartoine commented 4 years ago

Hey!

I have a JSON structure which is quite similar to this: image

Naturally, I've created a model where the property displayFields is decorated like that (where K is an enum type and V an array of a class (marked as jsonObject too)):

image

However, I have an issue while trying to parse my JSON.

Do you know a workaround or any solution to fix my issue? Do you know if it is possible to use @jsonMapMember for that case?

Thank you in advance!

Jakartoine commented 4 years ago

🎉 I think I found a workaround which seems to do the job! 🎉

I've created my own serializer/deserializer: image

Pretty weird as a solution and I think this should be integrated/handled somewhere into the library (not sure if it is a bug or a kind of "work as designed").

Here is the printed parsed property of the object in console: image

If it can help further users, I would be happy 👍

Neos3452 commented 4 years ago

Hi @Jakartoine! Thanks for opening an issue. Unfortunately you have encountered two different problems. One is sort of by design and the other is typescript limitation.

The first one is the accepted structure of maps in TypedJSON. It actually is not a dictionary but an array of {key: KeyType, value: ValueType} objects. I admit that this may not be the most friendly, but on the other hand allows to handle objects as key types.

The Typescript limitation is caused by how the types are emitted by typescript. As the generic types are erased, we don't really have a way of knowing the type that is hold by an array. We work around this for a number of types by providing custom decorators for them.

If you think this could be improved somehow just let me know.

Jakartoine commented 4 years ago

Hey @Neos3452, Thanks for your quick answer. I couldn't expect a quicker one!

I know what you mean and I can understand the idea of "custom decorators". In fact, that sounds perfect to handle my case.

What about a new decorator named 'jsonMapArrayMember'?

It will be the exact same as 'jsonMapMember' with an exception about the inner work where the Value Constructor is the generic type of the Value Array: image

The thing to know now is, is it possible to do something like that? Has any other developer ever needed such an operator? Because for my personal case, the workaround I've posted above is quite fine.

Otherwise, thank you for this library. I encourage developers to use it in my company. This allows us to get more control on our models and even more so those who have deep relationships inside themselves.

TypedJSON is a timesaving and will avoid a huge boilerplate code. I've already adopted it in one of our apps used by thousands of users. My only regret is that it's not as popular as it should be. And I believe this should be part of Typescript directly.

Neos3452 commented 4 years ago

Thanks for that, it means a lot :)

About your proposed solution I see one potential issue. We would need to define more decorators to support more combinations. However, for some time now, I was thinking about a different approach that could solve this issue, and others (like having an any type to skip the expected type check). The solution would be to use a special structure to define the types in the decorator. I was thinking about something like this:

    @jsonMapMember(String, ArrayT(MyClass))
    property: Map<string, MyClass[]>;

I actually prepared a POC, and you could take a look at the test that checks your particular situation here: https://github.com/Neos3452/TypedJSON/blob/type-descriptor/spec/map.spec.ts#L99

Hopefully, if typescript gets around and delivers a better reflection system this could be replaced with that.

What do you think?

Jakartoine commented 4 years ago

@Neos3452 Thank you for your investigation!

I believe what you've done should work for my case but also for the other ones.

Any idea about a further integration? 💯

PaulChernoch-Shell commented 2 years ago

The answer to this issue was helpful. I did not see in the documentation any examples of the expected text syntax of the input JSON for when deserializing a Map. You should add to the docs an explanation of the key/value array syntax that you require, with an example.