Tutorial: Parse JSON with LoganSquare

Hi, guys!

Today I want to present you a new JSON-parsing library – LoganSquare, written by BlueLine Labs. It is told to be the fasted available and quite easy to use, so I couldn’t miss it 😉 Below you will find an example Android project, which serializes and parses some objects.

Also, I have run Logan’s Benchmark project myself and indeed, the results are good. Not as good, as on their GitHub’s page, but still. Just to make everything clear, I have used Nexus 5 running Android 6.0.1 (ART).

Logan Square benchmark results

As you can see, LoganSquare wins in every category. Lets check how we can use it in our project, shall we?

Add ProGuard rules, as following:

proguard-rules.pro


 -keep class com.bluelinelabs.logansquare.** { *; } 
 -keep @com.bluelinelabs.logansquare.annotation.JsonObject class * 
 -keep class **$$JsonObjectMapper { *; }

We also need to add a classpath to android-apt plugin, for compile-time annotations. Just do this in build.gradle (project) file, like this:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {

  repositories {
    jcenter()
  }
  dependencies {
    classpath 'com.android.tools.build:gradle:2.1.0'
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
  }
}

allprojects {
  repositories {
    jcenter()
  }
}

task clean(type: Delete) {
  delete rootProject.buildDir
}

Now, we add LoganSquare library and apt compiler as Gradle dependencies in build.gradle (app module)


apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
android {
    compileSdkVersion 23 
    buildToolsVersion "23.0.3"

    defaultConfig { 
        applicationId "com.lomza.logansquare" 
        minSdkVersion 15 
        targetSdkVersion 23 
        versionCode 1 
        versionName "1.0"
    } 
    buildTypes { 
        release { 
            minifyEnabled false 
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard- rules.pro' }
    }
} 

dependencies { 
    compile fileTree(dir: 'libs', include: ['*.jar']) 
    testCompile 'junit:junit:4.12' 
    compile 'com.android.support:appcompat-v7:23.4.0' 
    apt 'com.bluelinelabs:logansquare-compiler:1.3.6' 
    compile 'com.bluelinelabs:logansquare:1.3.6' }

Of course, you might have different library’s versions used, but everything else should be the same. Anyway, try to compile the project at this time, in order to make sure there are no errors.

Now we need some data to operate on. I got inspired by JSON from here, simplified it a bit and put a few objects to the string. You can see it assigned to JSON_TO_PARSE class field here. And yes, the example project is available on GitHub, so feel free to grab it 😉

What we do next is add a few JsonObject class with JsonFields. I have separated two: Thumbnail and YouTubeVideo models.

YouTubeVideo.java


package com.lomza.logansquare.model;

import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonIgnore;
import com.bluelinelabs.logansquare.annotation.JsonObject;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

@JsonObject(fieldDetectionPolicy = JsonObject.FieldDetectionPolicy.NONPRIVATE_FIELDS_AND_ACCESSORS)
public class YouTubeVideo {
    private String id;
    private Date uploaded;
    private Date updated;
    private String category;
    private String title;
    private String description;
    private List tags;
    private Thumbnail thumbnail;
    private HashMap content;
    private int duration;
    private double rating;
    private long viewCount;
    private long commentCount;

    @JsonField(typeConverter = EnumStringConverter.class)
    public Status status;

    @JsonIgnore
    private boolean watched;

    public YouTubeVideo() {

    }

    public YouTubeVideo(String id, Date uploaded, Date updated, String category, String title,
        String description, List tags, Thumbnail thumbnail, HashMap content,
        int duration, double rating, long viewCount, long commentCount, Status status, boolean watched) {
        this.id = id;
        this.uploaded = uploaded;
        this.updated = updated;
        this.category = category;
        this.title = title;
        this.description = description;
        this.tags = tags;
        this.thumbnail = thumbnail;
        this.content = content;
        this.duration = duration;
        this.rating = rating;
        this.viewCount = viewCount;
        this.commentCount = commentCount;
        this.status = status;
        this.watched = watched;
    }

    // All getters and setters (skipped because of a bit length 🙂
    ...
    @Override
    public String toString() {
        return “{” +
        ” \”id\”:\”” + getId() + “\”,\n” +
        ” \”uploaded\”:\”” + getUploaded() + “\”,\n” +
        ” \”updated\”:\”” + getUpdated() + “\”,\n” +
        ” \”category\”:\”” + getCategory() + “\”,\n” +
        ” \”title\”:\”” + getTitle() + “\”,\n” +
        ” \”description\”:\”” + getDescription() + “\”,\n” +
        ” \”tags\”:” + getTags().toString() +
        ” ,\n” +
        ” \”thumbnail\”:” + getThumbnail().toString() +
        ” ,\n” +
        ” \”content\”:{\n” + getContent().toString() +
        ” },\n” +
        ” \”duration\”:” + getDuration() + “,\n” +
        ” \”rating\”:” + getRating() + “,\n” +
        ” \”viewCount\”:” + getViewCount() + “,\n” +
        ” \”commentCount\”:” + getCommentCount() + “,\n” +
        ” \”status\”: \”” + getStatus() + “\”\n” +
        “}”;
    }
}

I’ve used JsonObject.FieldDetectionPolicy.NONPRIVATE_FIELDS_AND_ACCESSORS policy, so the fields can be private and their values will be taken from public accessors. You can instead use FieldDetectionPolicy.NONPRIVATE_FIELDS (for public or package fields) or annotate each field separately. Although the last one is recommended by library authors, it depends on project’s and model’s preferences, so choose your own approach wisely 😉

You can see there’s a variety of types in YouTubeVideo class – String, int, long, double, List, HashMap<String, String>, boolean, also an enum with its custom converter – EnumStringConverter, and one field is marked with @JsonIgnore, so it will not be included in serialized JSON object. LoganSquare handles all those types just fine, so nothing to worry here. And the toString() method was added for a convenient logging.

For Date fields, DateConverter was added, in order to handle parsing and serializing of dates. You can use the @JsonField(typeConverter = DateConverter.class) annotation or set it globally in code, like I did in MainActivityLoganSquare.registerTypeConverter(Date.class, new DateConverter());, – easy and without ugly code around. Thanks to this line, serialized date looks like this – 28 May 2016 12:04.

Converter class (any class derived from TypeConverter) is just a helper class for handling type parsing and serialization. You can see different kind of usages here.

In Example project, there are two buttons: Serialize and Parse and a TextView for showing a result model.

LoganSquare parse and serialize screenshot

 

Serialize button click calls:


public void handleSerialization() {
  try {
        String jsonString = LoganSquare.serialize(videoList).replace(",", ",\n").replace("{", "{\n").replace("}", "}\n");
        Log.d(TAG, "[JSON.Serialized]:" + jsonString);
        resultTextView.setText(jsonString);
      } catch (IOException e) {
        e.printStackTrace();
      }
  }
}

And Parse button click calls this method:


public void handleParsing() {
  try {
    final List youTubeVideos = LoganSquare.parseList(JSON_TO_PARSE, YouTubeVideo.class);
    String parsedList = "";
    for (YouTubeVideo video : youTubeVideos) {
      Log.d(TAG, "[Object.Parsed]:" + video.toString());
      parsedList += video.toString();
      }
      resultTextView.setText(parsedList);
    } catch (IOException e) {
      e.printStackTrace();
  }
}

The end data is showed in LogCat, as well as displayed in the activity’s TextView. Note, the handy methods for parsing and serializing lists. It’s THAT easy!

Just to sum up, here are a few pros and cons I have noted myself, after using LoganSquare for a short time:

Pros

  • is really fast in both parsing and serialization
  • small library size
  • handy methods for lists parsing and serialization
  • useful converters
  • compile-time errors instead of run-time only

Cons

  • not much of a documentation, also not many questions & answers on StackOverflow
  • not many types supported
  • was not able to use ENUM(\”enum\”) values
  • only String keys supported in Map collections
  • Although the first commit for LoganSquare was a year ago, it’s only now that the library started to gain its popularity and has obtained a good shape and documentation. With this tutorial, I hope it will be even easier for you to start working with LoganSquare 🙂

Thanks for reading and leave your comments below! 😉

Like and share:

Published by

Tonia Tkachuk

I'm an Android Developer, writing code for living and for fun. Love beautiful apps with a clean code inside. Enjoy travelling and reading.