2

JSON4S を使用して JSON を生成しています。

条件が満たされる場合、次の製品を作成したいと考えています。

{"fld1":"always", "fld2":"sometimes"}

条件が満たされない場合、私は生産したいと思います:

{"fld1":"always"}

私がこれまでに試したことは次のとおりです。

val fld1 = "fld1" -> "always"

val json = if(condition) ("fld2" -> "sometimes") ~ fld1 else fld1

compact(render(json))

renderただし、これにより、 「Found: Product with Serializable. Required: org.json4s.package.JValue」でタイプの不一致が発生します。

興味深いのは、これがrender(("fld2" -> "sometimes") ~ fld1)機能することrender(fld1)です。問題は、 の推論された型にあるようですjson

どうすればこれを修正できますか?

4

3 に答える 3

4

現在の回答は両方とも適切な回避策を提供しますが、どちらもここで何が起こっているのかを説明していません。問題は、次のように 2 つの型がある場合です。

trait Foo
trait Bar

そして、一方から他方への暗黙の変換 (またはビュー):

implicit def foo2bar(foo: Foo): Bar = new Bar {}

Foofor itsthen句とBarfor its 句を含む条件文は、 andelseの最小上限として型指定されます(この場合は 、あなたの場合は)。FooBarObjectProduct with Serializable

これは、型推論システムが介入してFooBarそれを と見なすことはできないため、全体を として入力するだけBarです。

考えてみれば、これは理にかなっています。たとえば、そのような条件を喜んで処理する場合、両方の方法で暗黙的な変換を行うとどうなるでしょうか?

あなたの場合、then句は a として型付けされJObjectelse句は a(String, String)です。JObject後者から前者へのビューがありますが、型を明示的に宣言するか、コンテキストで式を使用することによって、全体を として終了させたいことを示さない限り、ここでは使用しません。でなければなりませんJObject

これらすべてを考えると、最も簡単な回避策は、次のような型注釈を提供することにより、両方の句が最初から適切に型付けされていることを確認することですfld1

val fld1: JObject = "fld1" -> "always"

これで、型注釈なしで、条件がそのまま適切に型付けされます。

于 2013-01-25T13:35:31.693 に答える
2

別のアプローチは、条件値をオプションにボックス化することです。

val json = fld1 ~ ("fld2" -> (if (condition) Some("sometimes") else None))

compact(render(json))
于 2013-01-25T12:42:42.067 に答える
2

私が考えることができる最も良い方法ではありませんが、自分で型を宣言することはうまくいくはずです:

val json: JObject = 
  if(condition) ("fld2" -> "sometimes") ~ fld1 else fld1

compact(render(json))

また、それ自体を助けるために型推論を取得できることに注意してください: 一度にレンダリングできる場合:

compact(render(
  if(condition) fld1 ~ ("fld2" -> "sometimes") else fld1  
))
于 2013-01-25T12:14:25.843 に答える