2017-01-31 1 views
3

Использование gson, я использую этот громоздкий подход, чтобы убедиться, требуемое свойство имеет требуемое значение:Проверьте свойство JSON присутствует, строка, и правильное значение

import com.google.gson.JsonElement; 
import com.google.gson.JsonObject; 
import com.google.gson.JsonParser; 

public class ScratchSpace { 

    public static void main(String[] args) { 

     // create json object from source data - in my real code, this is sourced externally 
     JsonObject json = new JsonParser().parse("{ \"product\": \"foobar\"}").getAsJsonObject(); 

     // does this object have a key called product, which is a string, and equal to our expected value? 
     boolean correctProduct = false; 
     if (json.has("product")) { 
      JsonElement productElement = json.get("product"); 
      if (productElement.isJsonPrimitive()) { 
       String product = productElement.getAsString(); 
       if ("foobar".equals(product)) { 
        correctProduct = true; 
       } 

      } 
     } 
     System.out.println("correctProduct = " + correctProduct); 
    } 

} 

Я почти уверен, что я» т делать это субоптимально. Есть ли простой, читаемый, короткоий однострочный лайнер для достижения того же?

Редактировать: если возможно, я бы хотел использовать gson.

+0

Вы изучали библиотеки запросов, такие как https://github.com/jayway/JsonPath? –

+0

Я искал ту же самую функцию в 'gson' недавно и не нашел ее – xenteros

ответ

1

Использование java.util.Optional, следующие работы:

final boolean correctProduct = Optional.ofNullable(json.get("product")) 
      .filter(JsonPrimitive.class::isInstance) 
      .map(JsonPrimitive.class::cast) 
      .map(JsonPrimitive::getAsString) 
      .filter("foobar"::equals) 
      .isPresent(); 
+0

Использование потоков - интересный подход; Я ожидал, что у него будет удобный способ сделать это. –

+0

На самом деле, 'javax.json.JsonObject' имеет метод getString с возможностью значения по умолчанию, если значение не является' String', но, видимо, Google скорее создал свою собственную модель данных ... ;-) PS ,: Я бы приветствовал, если бы больше разработчиков ушли от «return null в случае ошибки» к схеме «вернуть опцию». – Smutje

+1

@Smutje AFAIR, JSON Processing была представлена ​​на Java 7 еще до Java 8 с ее опциями, в то время как Gson был выпущен в 2008 году почти десять лет назад, поэтому я думаю, что авторы javax.json просто переосмыслили существующие библиотеки, такие как Гссона или Джексона. Возврат «null» дешевле, но да, это не так удобно для таких случаев, если один предпочитает oneliners ... –

0

Вы можете написать собственный десериализатор как this, зарегистрировать его и использовать fromJson метод, чтобы получить объект непосредственно из JSon строки. Таким образом, вы можете вернуть null или исключить исключение в десериализаторе, если строка json отсутствует в ожидаемом формате.

Обратите внимание, что вам не нужно устанавливать каждое поле отдельно. После выполнения пользовательских проверок вы можете использовать десериализацию по умолчанию от context.

EDIT: Если вы хотите получить только true/false вместо полного объекта, то вы можете написать MyBoolean класс, держа простой boolean значение и использовать fromJson метод десериализации для MyBoolean класса. Пользовательский десериализатор выполнит только нужные проверки и соответствующим образом настроит содержимое экземпляра MyBoolean. Кроме того, (я думаю), если вы расширите этот MyBoolean от Boolean, вы можете использовать его как boolean.

EDIT 2: Мне не приходилось указывать пример кода раньше. Вот что я предлагаю:

package io.ram.ram; 

import java.lang.reflect.Type; 

import com.google.gson.Gson; 
import com.google.gson.GsonBuilder; 
import com.google.gson.JsonDeserializationContext; 
import com.google.gson.JsonDeserializer; 
import com.google.gson.JsonElement; 
import com.google.gson.JsonParseException; 

public class Tester { 

    public static class MyBoolean { 
     private boolean value; 

     public void set(boolean value) { 
      this.value = value; 
     } 

     public boolean get() { 
      return value; 
     } 
    } 

    public static class MyAdapter implements JsonDeserializer<MyBoolean> { 

     public MyBoolean deserialize(JsonElement json, Type type, JsonDeserializationContext context) 
       throws JsonParseException { 
      MyBoolean result = new MyBoolean(); 
      result.set(false); 

      try { 
       result.set(json.getAsJsonObject().get("product").getAsString().equals("foobar")); 
      } catch (Exception e) { 

      } 
      return result; 
     } 

    } 

    public static void main(String[] args) { 
     Gson gson = new GsonBuilder().registerTypeAdapter(MyBoolean.class, new MyAdapter()).create(); 

     System.out.println(gson.fromJson("{\"product\": \"foobar\"}", MyBoolean.class).get()); 
     System.out.println(gson.fromJson("{\"product\": \"foobaz\"}", MyBoolean.class).get()); 
    } 

} 

Как я уже говорил, после того, как вы зарегистрируетесь адаптер типа для пользовательских сериализации, вы можете добиться того, что вы хотите с одной строкой. (Примечание: Boolean класс является окончательным, поэтому мы не можем расширить его Извините за эту неверную информацию.).

Вы можете параметризуем MyAdapter для строк "product" и "foobar" конечно, таким образом, вы не должны создавать такие классы для всех возможных случаев.

0

Я знаю, что ты сказал GSON, но подход, основанный на POJO джексон предлагает делает то, что вы хотите сделать просто слишком удобно, чтобы не размещать:

Простой POJO:

public class FooPojo { 
    @JsonProperty 
    private String product; 

    public String getProduct() { 
     return product; 
    } 

    public void setProduct(String product) { 
     this.product = product; 
    } 

    public boolean isProductEqualTo(String check) { 
     return product.equals(check); 
    } 
} 

Анализировать и проверить:

public static void main(String[] args) throws IOException { 
    ObjectMapper objectMapper = new ObjectMapper(); 
    FooPojo fooPojo = objectMapper.readValue("{ \"product\": \"foobar\"}", FooPojo.class); 
    System.out.println(fooPojo.isProductEqualTo("foobar")); 
} 
Смежные вопросы