Аргументы командной строки сохраняются как строки в массиве String
String[] args that is passed to
main () `.
java [program name] [arg1,arg2 ,..]
Аргументы командной строки - это входы, которые принимают из командной строки при запуске программы , Пропускаемые аргументы могут быть любыми. Который хранится в массиве args[]
.
//Display all command line information
class ArgDemo{
public static void main(String args[]){
System.out.println("there are "+args.length+"command-line arguments.");
for(int i=0;i<args.length;i++)
System.out.println("args["+i+"]:"+args[i]);
}
}
Пример:
java Argdemo one two
Выход будет:
there are 2 command line arguments:
they are:
arg[0]:one
arg[1]:two
Я решил использовать модуль Джексона для Scala .
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper
val mapper = new ObjectMapper() with ScalaObjectMapper
mapper.registerModule(DefaultScalaModule)
val obj = mapper.readValue[Map[String, Object]](jsonString)
Scala в целом не рекомендует использовать downcasting, и Play Json в этом отношении идиоматичен. Приведение в исходное состояние является проблемой, поскольку компилятор не может отследить возможность неправильного ввода или других ошибок. Получив значение типа Map[String, Any]
, вы сами - компилятор не может помочь вам отследить, какими могут быть эти значения Any
.
У вас есть пара альтернатив. Первый - использовать операторы пути для перехода к определенной точке дерева, где вы знаете тип:
scala> val json = Json.parse(jsonString)
json: play.api.libs.json.JsValue = {"key1": ...
scala> val k1Value = (json \ "key1" \ "subkey1" \ "k1").validate[String]
k1Value: play.api.libs.json.JsResult[String] = JsSuccess(value1,)
Это похоже на что-то вроде следующего:
val json: Map[String, Any] = ???
val k1Value = json("key1")
.asInstanceOf[Map[String, Any]]("subkey1")
.asInstanceOf[Map[String, String]]("k1")
Но прежний подход имеет то преимущество, что он терпит неудачу способами, которые легче рассуждать. Вместо потенциально трудного для интерпретации ClassCastException
исключения , мы просто получили бы хорошее значение JsError
.
Обратите внимание, что мы можем проверить в точке выше в дереве, если мы знаем, какую структуру мы ожидаем:
scala> println((json \ "key2").validate[List[Map[String, String]]])
JsSuccess(List(Map(j1 -> v1, j2 -> v2), Map(j1 -> x1, j2 -> x2)),)
Оба эти примера Play основаны на концепции классы типов - и, в частности, в экземплярах классов типов Read
, предоставляемых Play. Вы также можете предоставить свои собственные экземпляры классов типов для типов, которые вы определили сами. Это позволит вам сделать что-то вроде следующего:
val myObj = json.validate[MyObj].getOrElse(someDefaultValue)
val something = myObj.key1.subkey1.k2(2)
Или что угодно. Документация Play (ссылка выше) дает хорошее представление о том, как это сделать, и вы всегда можете задать дополнительные вопросы здесь, если у вас возникнут проблемы.
Чтобы обратиться к обновлению в вашем вопросе, можно изменить вашу модель, чтобы учесть различные возможности для key2
, а затем определить свой собственный экземпляр Reads
:
case class MyJson(key1: String, key2: Either[String, Map[String, String]])
implicit val MyJsonReads: Reads[MyJson] = {
val key2Reads: Reads[Either[String, Map[String, String]]] =
(__ \ "key2").read[String].map(Left(_)) or
(__ \ "key2").read[Map[String, String]].map(Right(_))
((__ \ "key1").read[String] and key2Reads)(MyJson(_, _))
}
Какой работает так:
scala> Json.parse(jsonString).as[List[MyJson]].foreach(println)
MyJson(v1,Left(v2))
MyJson(x1,Left(x2))
MyJson(y1,Right(Map(subkey1 -> subval1, subkey2 -> subval2)))
Да, это немного более многословно, но это предварительное многословие, за которое вы платите один раз (и это дает вам хорошие гарантии), а не кучу приведений это может привести к запутанным ошибкам во время выполнения.
Это не для всех, и, возможно, вам не по вкусу - это прекрасно. Вы можете использовать операторы пути для обработки подобных случаев или даже простого старого Джексона. Я бы посоветовал вам дать шанс подходу типа «класс», хотя есть крутая кривая обучения, но многие люди (включая меня) очень сильно это предпочитают.
Для дальнейшего ознакомления и в духе простоты вы всегда можете перейти к:
Json.parse(jsonString).as[Map[String, JsValue]]
Однако это вызовет исключение для строк JSON, не соответствующих формату (но я предполагаю, что это относится к подход Джексона также). JsValue
теперь можно обрабатывать следующим образом:
jsValueWhichBetterBeAList.as[List[JsValue]]
Я надеюсь, что разница между обработкой Object
и JsValue
с не является для вас проблемой (только потому, что вы жаловались на JsValue
является собственностью). Очевидно, это немного похоже на динамическое программирование на типизированном языке, который обычно не подходит (ответ Трэвиса - это обычно путь), но иногда это приятно, я думаю.
Вы можете просто извлечь значение Json, и Scala даст вам соответствующую карту. Пример:
var myJson = Json.obj(
"customerId" -> "xyz",
"addressId" -> "xyz",
"firstName" -> "xyz",
"lastName" -> "xyz",
"address" -> "xyz"
)
Предположим, у вас есть Json вышеупомянутого типа. Чтобы преобразовать его в карту, просто сделайте:
var mapFromJson = myJson.value
Это даст вам карту типа: scala.collection.immutable.HashMap $ HashTrieMap
Рекомендовал бы ознакомиться с сопоставлением с образцом и рекурсивными ADT в целом, чтобы лучше понять, почему Play Json рассматривает JSON как «гражданина первого класса».
При этом многие API-интерфейсы на основе Java (например, библиотеки Google Java) ожидают десериализации JSON как Map[String, Object]
. Хотя вы можете очень просто создать свою собственную функцию, которая рекурсивно генерирует этот объект с сопоставлением с шаблоном, простейшим решением, вероятно, будет использование следующего существующего шаблона:
import com.google.gson.Gson
import java.util.{Map => JMap, LinkedHashMap}
val gson = new Gson()
def decode(encoded: String): JMap[String, Object] =
gson.fromJson(encoded, (new LinkedHashMap[String, Object]()).getClass)
LinkedHashMap используется, если вы хотите сохранить порядок ключей во время десериализации (HashMap может использоваться, если порядок не имеет значения). Полный пример здесь .