
However, it is difficult for anybody but the biggest brands to be sustainable, without massive cuts into their margins. Amidst the retail apocalypse, when well-known retailers are failing and Amazon is ever expanding into fashion, shrinking margins are not what brands what to see.
Rockefeller suggests picking one of the Sustainable Development Goals and working towards that. She says “for new designers, if you are making something, make it as sustainably as possible. Try to find alternative packaging, find where your fabrics come from.” Rockefeller, who sits on the board of the Oceana, a non-profit to preserve the world’s oceans, adds that picking sustainable fabrics is especially important for ocean protection. Since up to 35% of the microplastics found in the ocean come from synthetic clothing, it is worth checking to see how your latest leggings are made.
The number of people wanting their clothes to be sustainable as well as beautiful is rising. As always, the brands that give the consumer what they want are those who are set to win.
223 Seiten, durchgehend vierfarb. Abb.
<issue_start><issue_comment>Title: #to_json/#to_yaml defined on every object
username_0: Since encountering the issue from #3450 again, I am convinced that printing a more helpful error message won't be enough. There needs to be a programmatic way to discover if `to_json`/`to_yaml` can be safely called on an object or not.

Right now, `a.responds_to? :to_json` returns `true` for any object, because `Object#to_json()` and `Object#to_json(IO)` are always defined if you `require "json"`. But calling `a.to_json` won't compile unless `a` has a `#to_json(JSON::Builder)` method.

As far as I can see, possible solutions are:

* A) Remove static definitions of `Object#to_json()` and `Object#to_json(IO)` and add these methods only if `#to_json(JSON::Builder)` is defined. This could be done manually (e.g. by including a module) and would of course be included with `JSON.mapping`. Or it might even be possible to add automatically if `#to_json(JSON::Builder)` is defined (for example using `finished` macro hook - or even `method_missing`). But the latter might be too much magic happening and there is always an issue documenting that.
* B) Rename `to_json(JSON::Builder)` so it can be distinguished from the synonymous wrapper methods - for example to `to_json_impl(JSON::Builder)`. Then, `a.responds_to? :to_json_impl` would show if an object has an actual implementation or not. There might perhaps be `Object#to_json(JSON::Builder)` as an alias but that will cause issues if people overwrite that alias instead of the implementation method.
* C) Add a module (for example `JSON::Serializable`) with an `abstract def to_json(JSON::Builder)` and all classes implementing this method should include the module (automatically included using `JSON.mapping`). `a.is_a? JSON::Serializable` would tell if it has an actual `to_json` implementation or not.
* D) Improve reflection capabilities to be able to query the argument types of a method. For example `a.responds_to? :to_json, JSON::Builder` would return true only if `#to_json(JSON::Builder)` is defined.
* E) Define `Object#to_json(JSON::Builder)` on every object as well and have it emit `null`. That's probably a reasonable default. I'm not sure about possible side effects, but I don't think this should be a huge issue. The biggest downside is that you can't distinguish if a class has a.

I think I would favour B) because it has the least impact though it's by far not optimal regarding naming. 
E) also sounds nice, but I'm not sure if it's feasible and I don't like the fact that you still can't tell if a class has a real implementation or just a dummy method. For most cases, emitting `null` might be the right way to handle missing serializers, but there might be other strategies to handle objects without serializer as well and there should be a way to determine that.
<issue_comment>username_1: A) is the way to go. `to_json` should only be defined in objects that have that method and its implementation.
<issue_comment>username_0: And how to implement?

A module could look like this:
```crystal
module JSON::Serializable
  def to_json : String
    String.build do |str|
      to_json str
    end
  end

  def to_json(io : IO)
    JSON.build(io) do |json|
      to_json(json)
    end
  end

  def to_pretty_json(indent : String = "  ") : String
    String.build do |str|
      to_pretty_json str, indent: indent
    end
  end

  def to_pretty_json(io : IO, indent : String = "  ")
    JSON.build(io, indent: indent) do |json|
      to_json(json)
    end
  end

  abstract def to_json(builder : JSON::Builder)
end
```

And similar for YAML.
<issue_comment>username_1: Probably, yes, but that will conflict with the idea I had regarding meta attributes.
<issue_comment>username_0: How so?
`.new(JSON::PullParser)` and `to_json(JSON::Builder)` need to be defined somehow anyway... would it be much effort to include a module?
<issue_comment>username_0: Maybe that module could even define those methods based on instance var reflection. Including classes need to be able to overwrite, of course.
<issue_comment>username_1: That's the idea. Then you would attach metadata to the instance vars to say how the are serialized.

The problem is, `String` also has `to_json`, but defining that method based on instance vars doesn't work. But, well, we can always redefine that in that case.

I think introducing a module with those methods is fine 👍
<issue_comment>username_2: The builder method doesn't need a distinct name anymore. It could simply be:

```crystal
module JSON::Serializable
  abstract def serialize(builder : JSON::Builder)
end

# ditto for YAML (or _any_ serialization format, for that matter)
module YAML::Serializable
  abstract def serialize(builder : YAML::Nodes::Builder)
end
```

And for deserialization:

```crystal
module JSON::Serializable
  module ClassMethods(T)
    abstract def deserialize(pull : JSON::PullParser) : T

    # `from_json` can be defined here
  end

  macro included
    extend ::JSON::Serializable::ClassMethods(self)
  end
end

module YAML::Serializable
  module ClassMethods(T)
    abstract def deserialize(ctx : YAML::ParseContext, node : YAML::Nodes::Node) : T

    # `from_yaml` can be defined here
  end

  macro included
    extend ::YAML::Serializable::ClassMethods(self)
  end
end
```

Renaming those methods has its own merit because they are not conversion methods in the usual sense and should not be considered overloads of the other `to_json` / `to_yaml` methods. Those other overloads showing up is partly what makes #3450 confusing.
<issue_comment>username_2: Revisiting this issue and I am finding that quite a number of types are only serializable but not deserializable, notably the doc types:

https://github.com/crystal-lang/crystal/blob/4140116007e387096deffa2aa13223bb262fa357/src/compiler/crystal/tools/doc/to_json.cr#L1-L11

There is obviously no way to reconstruct a `Crystal::Arg` back from the search index, but as long as `JSON::Serializable` is responsible for both serialization and deserialization, any attempt to rely on it for the argless `#to_json()` would ultimately force us to also write the deserializing constructor `.new(JSON::PullParser)` that always raises. In these cases, instead of further granularizing the `JSON::Serializable` API, we might have to define all the other `to_json`'s directly:

```crystal
class Crystal::Arg
  def to_json : String
    String.build do |str|
      to_json str
    end
  end

  def