Discussion:
[elm-discuss] How to do JSON export/import for apps?
Sandi Dušić
2017-12-25 00:28:25 UTC
Permalink
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?
--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
art yerkes
2017-12-25 22:04:25 UTC
Permalink
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:

https://medium.com/@prozacchiwawa/the-im-stupid-elm-language-nugget-14-ff31110ef643

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:

http://package.elm-lang.org/packages/Fresheyeball/elm-return/latest

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.
Post by Sandi Dušić
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?
--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Sandi
2017-12-29 15:49:36 UTC
Permalink
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.
Post by art yerkes
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.
ff31110ef643
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
http://package.elm-lang.org/packages/Fresheyeball/elm-return/latest
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.
Post by Sandi Dušić
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?
--
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
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Loading...