2012-03-23 3 views
3

У меня поток JSON генерируется программой на C++ на стороне сервера, которая в настоящее время находится в разработке. Мне дали образец полученного JSON, и я обеспокоен тем, что мне придется вручную разобрать json, что я не смогу использовать обычное сопоставление классов, предоставляемое такими инструментами, как GSON или Jackson.JSON to Java Объекты, лучшая практика для моделирования потока json

Пожалуйста, взгляните на следующий (несколько) надуманный пример, который они предоставили. Секции, которые меня интересуют, представляют собой метаданные «serie», имеющие разные параметры. Ключ - «ключ», например, присутствует только в одном из элементов массива. Не вызовет ли это проблемы, пытающиеся сопоставить этот массив с коллекцией определенного класса?

И наконец, я обеспокоен тем, что объект «point» не похож. Я очень слабо разбираюсь в JSON (будучи старомодным разработчиком java swing), но тот факт, что пары «ключевые точки» могут быть разными, - проблема.

Вся идея этого потока json состоит в том, чтобы описать таблицу, с помощью способов показать прогресс и предоставить механизм для запроса «большего количества» от основного оборудования. Также, если вам интересно, почему, я делюсь этим потоком данных с тонким клиентом (html-браузер).

Я исправлю, что это не будет легко преобразовать в объекты Java?

{ 
    "abort": "abort;session=sessionname", 
    "data": { 
    "metadata": [ 
     { 
     "protocol": "HTTP", 
     "serie": [ 
      { 
      "name": "k1", 
      "description": "xDR ID", 
      "tooltip": "ASDR Unique Identifier - UiD", 
      "type": "int64", 
      "key": "1" 
      }, 
      { 
      "name": "c1", 
      "description": "Answered", 
      "tooltip": "Request with Response", 
      "type": "bool" 
      }, 
      { 
      "name": "c2", 
      "description": "Active", 
      "tooltip": "Session status: active or closed/down", 
      "type": "bool" 
      } 
     ] 
     }, 
     { 
     "protocol": "DNS", 
     "serie": [ 
      { 
      "name": "k1", 
      "description": "xDR ID", 
      "tooltip": "ASDR Unique Identifier - UiD", 
      "type": "int64", 
      "key": "1" 
      }, 
      { 
      "name": "k2", 
      "description": "Transaction ID", 
      "type": "int64", 
      "key": "1", 
      "display": "number" 
      }, 
      { 
      "name": "k3", 
      "description": "Client", 
      "tooltip": "Source IP Address", 
      "type": "string", 
      "key": "1", 
      "display": "ip" 
      } 
     ] 
     } 
    ], 
    "summary": [ 
     { 
     "timestamp": "1331192727", 
     "protocol": "HTTP", 
     "activity": "www.google.com", 
     "results": "OK", 
     "point": { 
      "k1": "1", 
      "c1": "true", 
      "c2": "true" 
     } 
     }, 
     { 
     "timestamp": "1331192727", 
     "protocol": "DNS", 
     "activity": "www.google.com", 
     "results": "OK", 
     "point": { 
      "k1": "1", 
      "k2": "1.1.4.229" 
     } 
     } 
    ] 
    }, 
    "progress": { 
    "perc": "100" 
    }, 
    "more": "13,39,1331192727,1331192760,27236,1.1.4.229,limit=1000,session=sessionname" 
} 

Благодарим за любые советы, которые вы можете предоставить.

-D Klotz

ответ

4

С GSON, предполагая, что класс вы десериализация в имеет поле для всех имен, которые появляются в формате JSON, поля не найдено в формате JSON только останутся пустой:

https://sites.google.com/site/gson/gson-user-guide#TOC-Finer-Points-with-Objects

«в то время десериализации, недостающее запись в результатах JSON в установке соответствующего поля в объекте обнулить»

вещей становятся немного более сложными, если имена произвольного поля ара e разрешено в JSON - например, если Point разрешает c1, c2, ... cn. Но вы можете справиться с этим с помощью специального десериализатора.

https://sites.google.com/site/gson/gson-user-guide#TOC-Writing-a-Deserializer

Edit:

Вот как вы можете написать собственный десериализатор для Поинта:

private class DateTimeDeserializer implements JsonDeserializer<Point> { 
    public Point deserialize(JsonElement json, Type typeOfT, 
      JsonDeserializationContext context) throws JsonParseException { 
     List<PointPart> parts = Lists.newArrayList(); 

     for(Map.Entry<String,JsonElement> entry : 
       json.getAsJsonObject().entrySet()) { 
      char type = ; 
      int index = Integer.parseInt(entry.getKey().substring(1)) - 1; 

      while(parts.size() <= index) { 
       parts.add(new PointPart()); 
      } 

      PointPart part = parts.get(index); 
      switch(entry.getKey().charAt(0)) { 
      case 'c': 
       part.c = entry.getValue().getAsBoolean(); 
       break; 
      case 'k': 
       part.k = entry.getValue().getAsInt(); 
       break; 
      } 
     } 

     return new Point(parts); 
    } 
} 

class Point { 
    List<PointPart> parts; 

    Point(List<PointPart> parts) { 
     this.parts = parts; 
    } 
} 

class PointPart { 
    boolean c; 
    int k; 
} 
+0

Спасибо. Если в json существует поле, но не в классе, что происходит? –

+0

Я считаю, что он обычно генерирует исключение синтаксического анализа. Вы можете заставить игнорировать эти поля, создав «ExclusionStrategy», который исключает любое поле, которое не отображается в целевом классе. (Но настраиваемый десериализатор - лучший вариант) –

+0

Я надеюсь избежать написания пользовательского десериализатора, так как я поймал это довольно рано в цикле разработки. Я еще немного поцарапаю себе голову. Спасибо за совет. –

2

Я бы больше озабочен тем, что выглядит полями метаданных в данном поток. Атрибуты верхнего уровня «abort» и «more» выглядят как какая-то структурированная строка, которую вам, возможно, придется разбирать? Кроме того, вам просто нужно смоделировать каждый объект Java с максимально возможным набором полей, которые будут отправляться из вашей внешней программы. Вам не нужно беспокоиться о том, что если переданные данные имеют одно или несколько полей, большинство библиотек JSON просто десериализуют нуль в этом случае. Кроме того, большинство библиотек JSON также позволят вам указать, что вы хотите игнорировать неизвестные входящие поля.

Таким образом, между десериализацией нулевого значения для отсутствующих полей и игнорированием дополнительных полей вы должны быть хороши для анализа.

+0

Итак, вы говорите, что дополнительные поля в потоке json игнорируются? Я собираюсь выйти на конечность и предположить, что это зависит от библиотеки? –

+0

Да, это зависит от библиотеки и более того, от конфигурации библиотеки. Например, это поведение отключено по умолчанию в Jackson, но может быть включено с настройкой конфигурации. – Perception

+0

Я не могу проголосовать или отметить более одного ответа. Я бы отметил это как ответ. Спасибо за помощь. –

1

Нет, это не особенно сложно десериализовать в объекты Java.JSON не имеет много подсказок о вводе информации, отличной от их примитивов. Большая часть беспокойства по поводу потери информации о типе может быть восстановлена ​​либо путем поиска объекта, который требуется десериализовать, либо предоставить пользователю объект, который они хотят десериализовать. Именно так работает flexjson, и у вас есть много гибкости, чтобы определить в каждой точке, как десериализовать его. Он поставляется с разумными значениями по умолчанию для большинства проблем, но вы всегда можете присоединить ObjectFactory к определенному классу или пути в потоке JSON.

http://flexjson.sourceforge.net