0

I am trying to write a simple utility to check whether a JsValue is null or empty. I have this:

def is_nullOrEmpty(x: JsValue): JsBoolean = {
  JsBoolean(
    (x) match {
      case _ => x == null
      case _ => x.toString().isEmpty  
    }
  )
}

I am fairly new to Scala + Play and I am not sure whether this is the correct way to go about.

Alternatively this:

def is_nullOrEmpty(x: JsValue) = x == null || x.toString().trim.isEmpty

Where I am also including .trim

Can you help?

Tomer Shetah
  • 8,413
  • 7
  • 27
  • 35
panza
  • 1,341
  • 7
  • 38
  • 68
  • 1
    I don't understand - why is the output of a method named as `is_nullOrEmpty` is `JsBoolean` ? Did you mean `Boolean` ? – sarveshseri Jan 14 '21 at 17:55

2 Answers2

2

I don't understand - why is the output of a method named as is_nullOrEmpty is JsBoolean ? Did you mean Boolean ?

def isNullOrEmpty(x: JsValue): Boolean = x match {
  case null => true
  case JsNull => true
  case _ => false
}

In case you also want to check the emptiness of String or Array for your JsValue then,

def isNullOrEmpty(x: JsValue): Boolean = x match {
  case null => true
  case JsNull => true
  case JsString(string) => string.trim.isEmpty
  case JsArray(array) => array.isEmpty
  case _ => false
}

Or, if you wanted to convert it to JsBoolean and return null if it is not a compatible value,

def convertToJsBoolean(x: JsValue): JsBoolean = x match {
  case jsBoolean: JsBoolean => jsBoolean
  case _ => null
}

In this case, you can also use Option[JsBoolean] as your output type,

def convertToJsBoolean(x: JsValue): Option[JsBoolean] = x match {
  case jsBoolean: JsBoolean => Option(jsBoolean)
  case _ => None
}
sarveshseri
  • 13,738
  • 28
  • 47
  • 1
    `null` should never ever be passed as `JsValue` ... Never – cchantep Jan 14 '21 at 19:54
  • `can` and `could` have always been at odds with `should`. – sarveshseri Jan 14 '21 at 21:23
  • If you intend to use null, use Java lib – cchantep Jan 14 '21 at 21:27
  • Are you serious ? Just go and count the null-usage in source code of scala std-lib, cats, zio, circe and many other Scala libs. Then you can tell the authors of all these libs to go use Java libs instead. – sarveshseri Jan 14 '21 at 21:35
  • Can you stop the users of your methods from passing `null` parameters using Scala ecosystem only ? Specially when the requirement is explicitly to identify `null`, which means that the use cases pose a substantial possibility of `null` values. – sarveshseri Jan 14 '21 at 21:40
  • You cannot, due to the very nature of JVM, that doesn't mean that's a good practice, and it should rather be handled as a failure, not a valid case. – cchantep Jan 14 '21 at 23:13
  • Its strange to think that a method named `isNullOrEmpty` should fail on `null` input, just because you want to encourage people to avoid `null` as far as possible. Yes, `null` values can cause a lot of problems (and people should avoid `null`) but you need to look at the context of usage. I don't think `null` is any different from other features like `implicits`, both can be abused, both require caution and can the verdict about their usage depends on context. An overly simplistic statement like "never use null" is nothing more than senseless noise. – sarveshseri Jan 15 '21 at 09:17
  • If you accept `null` in Scala as a first citizen language feature, as implicit (at least for type class, as even implicit for conversion are discouraged/deprecated), and not as a edgecase due to the JVM, really, that's a bad practice. You should only handle it when there is absolutely no other possibility, like `var`. – cchantep Jan 15 '21 at 11:27
  • Are you still arguing about usage of `null`, when your use case is to write a method which tells you whether the input is `null` or not ? Can there even be a more authentic place to discount the usage of `null` ? This seems like a pointless argument where you keep on repeating the obvious "fact". And `null` is a first class citizen in Scala. – sarveshseri Jan 15 '21 at 19:59
  • That's not pointless as such test method such not happened to be required, that's an x/y question. Let's disagree on the `null` support. – cchantep Jan 15 '21 at 20:13
  • First of all, who even advocates the use of `null` ? If you think that such a method should not be required, then look at `Option` itself. Also, you need to look at Scala ecosystem and you will find real unwarranted usage of `null` in almost every major library. If you want to see examples of avoidable usage of `null`, then see this - https://github.com/zio/zio/blob/master/core/shared/src/main/scala/zio/ZQueue.scala#L299 and https://github.com/zio/zio/blob/master/core/shared/src/main/scala/zio/ZQueue.scala#L528. – sarveshseri Jan 15 '21 at 20:21
  • The realy x/y problem here can be summarised as followos. Real requirement - Check whether my input is `null`. @cchantep - No forget about that. We should never use `null`, go and redefine your problem without involving `null`. You seem to forget that `null` is not the problem, the real problem is that `arbitrary nullability` (where as `exclusive nullabilty` is more manageable) can lead to a lot of problems. And `arbitrary nullability` is already there in Scala. – sarveshseri Jan 15 '21 at 20:30
  • And when almost every real world interaction of every Scala program (any IO) goes through Java implemenations (socket, inputstreams, outputstreams, files etc), which love to deal with `null` values, how can you even write a meaningful Scala program without handling `null` values. – sarveshseri Jan 15 '21 at 20:41
1

You can use Option. Please try the following:

def is_nullOrEmpty(x: JsValue): JsBoolean = Option(x) match {
  case None =>
    JsFalse
  case Some(value) =>
    if (Json.stringify(value) == "") {
      JsFalse
    } else {
      JsTrue
    }
}

Or even easier in one liner:

def is_nullOrEmpty1(x: JsValue): JsBoolean = JsBoolean(Option(x).exists(Json.stringify(_) != ""))

Having said that, the check of an empty string is redundant, as elaborated at Why does JSON.parse fail with the empty string? and in many other posts.

Code run at Scastie.

Tomer Shetah
  • 8,413
  • 7
  • 27
  • 35
  • Thank you for your help, I have set as the accepted answer. I have a question in that respect. If I use the following: ```def is_nullOrEmpty(x: JsValue): JsBoolean = { x match { case JsString(value) => JsBoolean(value.isEmpty) case JsNull => JsTrue case JsArray(value) => JsBoolean(value.isEmpty) } }``` It does fail when validating an empty string, but I still not sure why. Can you give me any insight? – panza Jan 21 '21 at 14:31
  • @paranza you need to use `case JsString(value) => JsBoolean(value.nonEmpty)` to get `JsTrue` when the string is not empty. Currently you check if the string is empty, it is , and you get true. This is not what you want. – Tomer Shetah Jan 21 '21 at 14:35
  • thank you, appreciated. I guess the idea is similar for the bit with the JsArray, right? – panza Jan 21 '21 at 15:02