How to do JSON export/import for apps?

119 views
Skip to first unread message

Sandi Dušić

unread,
Dec 24, 2017, 7:28:25 PM12/24/17
to Elm Discuss
I want to add persistence to my app. Only parts of the model need to be saved. For this, I need a way to decode/encode the model to and fro' JSON.

My original idea was to have a `-- JSON` section in each elm architecture component. Parent components would use their children's decode/encode methods to write their own. I ran into some problems doing it this way, namely code duplication between the `init` and `decode` methods and the handling of `Cmd`s. Is there a better way to do it or any general advice?

art yerkes

unread,
Dec 25, 2017, 5:04:25 PM12/25/17
to Elm Discuss
You're on the right track not duplicating json decoding and encoding when they're part of larger things.  You can do the same with init, too.

Having state in components comes up a lot as a question in elm, I wrote about my take on how this should ideally work:


In other words, the real app is a set of messages that a concentrated, hidden state.  If components need small, non-serialized state such as whether a menu is open or a moveable object has handles shown, then local state is appropriate (and shouldn't be serialized).  If the information has more reach and needs save and restore, then store it in the State, and pass that state down to the components, allowing them to bubble up messages to change it.

The important part is that you're decoupling the app's state from the shape of the UI and enabling code to be written about it without coupling that code to the views; instead, the views and the app's other code cooperate over some data you define to get the best from each.  In this model, you'll move the types and codecs to a tier above State, where they'll be imports to everything downstream, and not isolate the types themselves in views.  My experience suggests that encapsulation isn't as important as it is elsewhere when you don't have to worry about mutation.

If you're having trouble sorting out how to handle the initial Cmd result from init, try using:


Ideally, there won't be duplication between your decoder and init ... worst case, you'd decode first, then copy the data you needed or wanted afterward, providing defaults in the bad decode case.

Sandi

unread,
Dec 29, 2017, 10:49:42 AM12/29/17
to elm-d...@googlegroups.com
Hi Art, thanks for your input.

From what I understand, your answer to my original question is affirmative, so that's how I shall do it. I've found different ways to write init and decode so that there are no duplication problems. I'm still unhappy with how little of it is validated by the compiler or automated. For example, if my component has a text field, then its decoder and encoder are connected only by me being careful to use the same name string in both functions.

I must admit I do not understand the other part about having persistent data separated. I recognize that my Model records keep two different types of fields, data and UI state. I also recognize that that dichotomy correlates well with other problems, like deciding when to save/sync, undo functionality and serialization (all of which are only concerned with the first type). I've actually been wondering as to how I'd accomplish those in my app in a way that's validated by the type system and/or automated. If it's all in the same record, than I'd manually have to look for the branches of my update function to see where the first kind of field was changed and then do something about it (prompt a sync, save the previous state for undoing etc.).

Could you provide any additional resources or comments as to what the best solution is? I'm struggling with your blogpost. I'll try reading it a few more times.



--
You received this message because you are subscribed to a topic in the Google Groups "Elm Discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elm-discuss/qMH59fxIMjY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elm-discuss+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages