2016-06-21 13 views
2

Пусть следующий простой JSON документ:Как изменить значение и тип в JSON с использованием объектива аргонаута?

 { 
     "key" : "val1" 
     } 

я хотел бы обновить значение «ключ», но в то же время и изменить его тип, поэтому из строки изменить его на междунар. Теперь, используя HCURSOR, как показано ниже, можно и прямо вперед, чтобы сделать это:

val cursor = js.hcursor 
val position = (cursor --\ "key") >-> (_ => jNumber(1)) 

Под «погибель» выше позиции я в конечном итоге, новый JSON, где «ключ» имеет числовое значение, а не строку , что идеально.

Можно ли использовать то же самое с помощью объективов? Я попытался сделать следующее:

val lense = jObjectPL >=> 
      jsonObjectPL("key") >=> 
      jNumberPL 
lense.mod(_ => JsonBigDecimal(1), js) 

Но хотя я не получаю сообщение об ошибке также не работает, в конце концов, я в конечном итоге с оригинальным JSon документа в неизменном виде. Однако, если я уважаю тип данных, все работает так, как должно. Есть ли причина, по которой линзы должны использоваться только для модификаций одного и того же типа данных? Или я просто делаю что-то ужасно неправильное :)

ответ

4

Нет, ничего страшного, вы почти там. Проблема в том, что этот путь:

jObjectPL >=> jsonObjectPL("key") >=> jNumberPL 

Переходит к ряду JSON в "key". Ваш js не имеет номера JSON на клавиатуре, поэтому объектив не указывает ни на что, и модификация ничего не влияет.

Вы можете это исправить, просто удалив последний шаг от объектива:

val lens = jObjectPL >=> jsonObjectPL("key") 

Это просто переходит к "key" поле, но не ставит ограничений на какие-то значения JSON это. После этого вы можете изменить его на то, что вы хотите:

scala> val lens = jObjectPL >=> jsonObjectPL("key") 
lens: scalaz.PLensFamily[... 

scala> lens.mod(_ => jNumber(JsonBigDecimal(1)), js) 
res0: argonaut.Json = {"key":1} 

Заметим, что поскольку линза указывает на значение Json, а не в JsonNumber, вам придется обернуть JsonBigDecimal в jNumber, чтобы типы выстраиваться.

+0

Спасибо за быстрый ответ @Travis! очень признателен. Читая документацию для линз и Argonaut, у меня создалось впечатление, что вы всегда должны определять тип данных JSON, который вы ожидаете. Но я думаю, что это часть человеческой природы, чтобы усложнять вещи несколько раз :) – cpard

+0

@cpard Yep :). В этом случае вы ожидаете строку JSON в этой позиции, но если вы добавите 'jStringPL' в объектив, вы не сможете изменить этот тип. –