如何使用Apache Avro序列化JSON文档,然后将其写入Cassandra?

时间:2013-09-15 03:26:36

标签: java json cassandra jackson avro

这些天我一直在阅读很多关于Apache Avro的内容,我更倾向于使用它而不是使用JSON。目前,我们正在做的是,我们使用JSON序列化Jackson文档,然后为每个JSON将序列化Cassandra文档写入row key/user id。然后我们有一个REST服务,它使用行键读取整个JSON文档,然后对其进行反序列化并进一步使用它。

我们会像这样写入Cassandra -

user-id   column-name   serialize-json-document-value

下面是一个示例,显示了我们写入Cassandra的JSON文档。此JSON文档适用于特定的行键/用户ID。

{
  "lv" : [ {
    "v" : {
      "site-id" : 0,
      "categories" : {
        "321" : {
          "price_score" : "0.2",
          "confidence_score" : "0.5"
        },
        "123" : {
          "price_score" : "0.4",
          "confidence_score" : "0.2"
        }
      },
      "price-score" : 0.5,
      "confidence-score" : 0.2
    }
  } ],
  "lmd" : 1379214255197
}

现在我们正在考虑使用Apache Avro,以便我们可以通过使用Apache Avro进行序列化来压缩此JSON文档,然后将其存储在Cassandra中。我有几个问题 -

  1. 是否可以首先使用Apache Avro序列化上述JSON文档,然后将其写入Cassandra?如果是的话,我该怎么做?任何人都可以提供一个简单的例子吗?
  2. 我们还需要在从REST服务中读取Cassandra时反序列化它。这也有可能吗?
  3. 下面是我的简单代码,它序列化JSON文档并在控制台上打印出来。

    public static void main(String[] args) {
    
        final long lmd = System.currentTimeMillis();
    
        Map<String, Object> props = new HashMap<String, Object>();
        props.put("site-id", 0);
        props.put("price-score", 0.5);
        props.put("confidence-score", 0.2);
    
        Map<String, Category> categories = new HashMap<String, Category>();
        categories.put("123", new Category("0.4", "0.2"));
        categories.put("321", new Category("0.2", "0.5"));
        props.put("categories", categories);
    
        AttributeValue av = new AttributeValue();
        av.setProperties(props);
    
        Attribute attr = new Attribute();
        attr.instantiateNewListValue();
        attr.getListValue().add(av);
        attr.setLastModifiedDate(lmd);
    
        // serialize it
        try {
            String jsonStr = JsonMapperFactory.get().writeValueAsString(attr);
    
            // then write into Cassandra
            System.out.println(jsonStr);
        } catch (JsonGenerationException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

    Serialzie JSON文档看起来像这样 -

    {"lv":[{"v":{"site-id":0,"categories":{"321":{"price_score":"0.2","confidence_score":"0.5"},"123":{"price_score":"0.4","confidence_score":"0.2"}},"price-score":0.5,"confidence-score":0.2}}],"lmd":1379214255197}
    

    AttributeValueAttribute类正在使用Jackson Annotations

    还有一个重要的注意事项,上面的json文档中的属性将根据列名称进行更改。我们为不同的列名称提供了不同的属性。某些列名称将具有两个属性,一些将具有5个属性。因此,根据我们的元数据,上述JSON文档将具有正确的属性及其值。

    我希望这个问题足够明确。任何人都可以为此提供一个简单的示例如何使用Apache Avro实现这一目标。我刚开始使用Apache Avro,所以我遇到了很多问题..

2 个答案:

答案 0 :(得分:0)

Avro需要一个架构,所以你必须在使用它之前设计它;并且使用与自由形成的JSON有很大不同。

但是,您可能需要考虑Smile - JSON的一对一二进制序列化,而不是Avro,专为您可能想要在JSON和二进制数据之间来回转换的用例而设计;例如,使用JSON进行调试,或者在为Javascript客户端提供服务时。

杰克逊拥有微笑后端(见https://github.com/FasterXML/jackson-dataformat-smile),这实际上是使用微笑而不是(或除了)JSON之外的单行更改。 许多项目使用它(例如,弹性搜索),它是成熟稳定的格式;和Jackson的工具支持对于不同的数据类型是广泛的。

答案 1 :(得分:0)

由于你已经使用过jackson,你可以试试Jackson dataformat module to support Avro-encoded data