Tag Archives: GsonBuilder

How to Mask JSON Confidential/Personal Information in logs :JAVA


Here you will see all steps to mask confidential/ information like credit card, CVV, Exp date,  SSN, password etc. So that it will print in mask form as ****** so that unauthorize use will not misuse of others information.

Here using Google GSON and GsonBuilder converting Java object to JSON and again converting JSON to Java Object.

By using Java refelection api’s replacing SPI fields data with *******.

Input JSON File AccountDetail


{
  "firstName": "Saurabh",
  "lastName": "Gupta",
  "address": {
    "addressLine1": "Noida City Center",
    "city": "Noida",
    "state": "UP",
    "pincode": "India",
    "country": "20310"
  },
  "creditCardDetail": {
    "cardNumber": "1234567890123456",
    "cvv": "123",
    "expDate": "12/90"
  }
}

 

Code to Mask JSON

package com.mask.json;

import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class MaskJSONTest {
	static Set fieldSet = new HashSet();
	static List fieldNames = Arrays.asList("cardNumber", "cvv", "expDate");

	public static void main(String[] args) throws IOException {
		StringBuilder contentBuilder = new StringBuilder();
		try (Stream stream = Files.lines(
				Paths.get(
						"D:\\Saurabh Gupta\\Workspace\\JavaTestExamples\\src\\main\\resources\\AccountDetail.json"),
				StandardCharsets.UTF_8)) {
			stream.forEach(s -> contentBuilder.append(s).append("\n"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		//Create GSON object
		//apply NullSearialization and Pretty formatting by GSON Builder
		Gson gson = getJsonBuilder().create();
		AccountDetail accounDetail = gson.fromJson(contentBuilder.toString(), AccountDetail.class);
		mask(accounDetail);
		System.out.println(gson.toJson(accounDetail));
	}
	public static GsonBuilder getJsonBuilder()
	{
		GsonBuilder builder = new GsonBuilder();

		// Setting for formatted output and serialize null value
		builder.setPrettyPrinting().serializeNulls();

		return builder;
	}

	public static void mask(Object object) {
		try {
			Field[] fields = object.getClass().getDeclaredFields();
			Object value = null;
			for (int i = 0; i <span id="mce_SELREST_start" style="overflow:hidden;line-height:0;"></span>&lt; fields.length; i++) {
				fields[i].setAccessible(true);
				value = fields[i].get(object);
				if (value != null &amp;&amp; fieldSet.add(fields[i].getName())) {
					if (fields[i].getType().isArray()
							|| fields[i].getType().getCanonicalName().startsWith(&quot;com.mask.json&quot;)) {
						mask(value);
					} else {
						if (fieldNames.contains(fields[i].getName()) &amp;&amp; fields[i].get(object) != null) {
							fields[i].set(object, replaceDigits((String) fields[i].get(object)));
						}
					}
				}

			}
		} catch (IllegalAccessException ex) {
			ex.printStackTrace();
		}
	}

	private static String replaceDigits(String text) {
		StringBuffer buffer = new StringBuffer(text.length());
		Pattern pattern = Pattern.compile(&quot;\\d&quot;);
		Matcher matcher = pattern.matcher(text);
		while (matcher.find()) {
			matcher.appendReplacement(buffer, &quot;X&quot;);
		}
		return buffer.toString();
	}

}

Model Classes


package com.mask.json;

public class AccountDetail {
private String firstName;
private String lastName;
private AddressDetail address;
private CreditCardDetail creditCardDetail;
public AccountDetail(String firstName, String lastName, AddressDetail address, CreditCardDetail creditCardDetail) {
	super();
	this.firstName = firstName;
	this.lastName = lastName;
	this.address = address;
	this.creditCardDetail = creditCardDetail;
}
public String getFirstName() {
	return firstName;
}
public void setFirstName(String firstName) {
	this.firstName = firstName;
}
public String getLastName() {
	return lastName;
}
public void setLastName(String lastName) {
	this.lastName = lastName;
}
public AddressDetail getAddress() {
	return address;
}
public void setAddress(AddressDetail address) {
	this.address = address;
}
public CreditCardDetail getCreditCardDetail() {
	return creditCardDetail;
}
public void setCreditCardDetail(CreditCardDetail creditCardDetail) {
	this.creditCardDetail = creditCardDetail;
}

}


package com.mask.json;

public class AddressDetail {

private String addressLine1;
private String city;
private String state;
private String pincode;
private String country;

public AddressDetail(String addressLine1, String city, String state, String pincode, String country) {
	super();
	this.addressLine1 = addressLine1;
	this.city = city;
	this.state = state;
	this.pincode = pincode;
	this.country = country;
}
public String getAddressLine1() {
	return addressLine1;
}
public void setAddressLine1(String addressLine1) {
	this.addressLine1 = addressLine1;
}
public String getCity() {
	return city;
}
public void setCity(String city) {
	this.city = city;
}
public String getState() {
	return state;
}
public void setState(String state) {
	this.state = state;
}
public String getPincode() {
	return pincode;
}
public void setPincode(String pincode) {
	this.pincode = pincode;
}
public String getCountry() {
	return country;
}
public void setCountry(String country) {
	this.country = country;
}

}

package com.mask.json;

public class CreditCardDetail{
private String cardNumber;
private String cvv;
private String expDate;

public CreditCardDetail(String cardNumber, String cvv, String expDate) {
	super();
	this.cardNumber = cardNumber;
	this.cvv = cvv;
	this.expDate = expDate;
}

public String getCardNumber() {
	return cardNumber;
}
public void setCardNumber(String cardNumber) {
	this.cardNumber = cardNumber;
}
public String getCvv() {
	return cvv;
}
public void setCvv(String cvv) {
	this.cvv = cvv;
}
public String getExpDate() {
	return expDate;
}
public void setExpDate(String expDate) {
	this.expDate = expDate;
}

}

Output Masked JSON :

{
“firstName”: “Saurabh”,
“lastName”: “Gupta”,
“address”: {
“addressLine1”: “Noida City Center”,
“city”: “Noida”,
“state”: “UP”,
“pincode”: “India”,
“country”: “20310”
},
“creditCardDetail”: {
“cardNumber”: “XXXXXXXXXXXXXXXX”,
“cvv”: “XXX”,
“expDate”: “XX/XX”
}
}

Related Posts

Below are some more masking ways for different type of data like XML, JSON and printing objects before logging , sending to page or transferring over network.

Log4j2: How to Mask Logs Personal/Confidential/SPI Information

How to MASK XML Confidential/Personal Data : JAVA

How to mask JAVA Object confidential/personal information in logs while Printing

Advertisements

How to exclude fields from JSON while parsing by GSON/GsonBuilder?


In below previous exaxmples. We discussed about to convert JAVA object to/ from to JSON and pretty formatting and null serailization of fields for JSON conversion. Now here we discussed about how to exclude fields/object while converting to JSON.

How to convert Java object to / from JSON by (GSON)

How to do JSON pretty formatting and Null Serialization (GSON/GsonBuilder)

GSON provide two ways to exclude fields from JSON by GsonBuilder:

  • @Expose Annotation
  • Custom Annotation

@Expose Annotation

By using the @Expose annotations and then using the excludeFieldsWithoutExposeAnnotation() method on the GsonBuilder will ignore all fields except the ones that have been exposed using the @Expose annotation.

Custom Annotation

By defining a custom annotation and ignoring fields that are annotated with exclusion class by extending ExclusionStrategy interface implementing that by using below GsonBuilder methods can ingnore/exclude fields from JSON.

Boolean shouldSkipField(FieldAttributes f);

public boolean shouldSkipClass(Class clazz);

Pre-Requisite:

  • JAVA 8
  • Maven 3
  • GSON Jar as below.

GSON Dependency:

 <dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.2</version>
 </dependency>

In below example fields middleName,educationDetail and experienceDetail will not serialize because not having @Expose annotation on it and field country will also not serialize because of having @Country annotation. Here you will see how to unsearilize all these

package gsonexamples;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import model.AlbumImages;
import model.Albums;
import model.Country;
import model.Dataset;
import model.Employee;
import util.CustomExclusionStrategy;

class GsonConvertJavaObjectToJSONExclusion {

	public static void main(String[] args) {
		Employee employee= getJavaObject();
		//CustomExclusionStrategy that will exclude the Country field.
// We also allow only those fields that have been exposed using the @Expose
//annotation

				Gson gson = new GsonBuilder()
				.setPrettyPrinting()
				.serializeNulls()
				.setExclusionStrategies(new CustomExclusionStrategy(Country.class))
				.excludeFieldsWithoutExposeAnnotation()
				.create();

		System.out.println(gson.toJson(employee));

	}

	public static  Employee getJavaObject()
	{
		Employee employee=new Employee("C123","Saurabh" ,"Kumar","Gupta","Tech Lead",50000,"Alpharetta,GA","Dallas, TX","1231231230",null,null);
		return employee;
	}

}

package util;

import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;

import model.Country;
import model.Dataset;

/**
 * This class use custom exclusion policy. We want to ignore all fields that
 * have been annotated with the Country annotation. Note that we can also ignore
 * fields based on name or type. This same type policy can be applied to any *  class.
 *
 */
public class CustomExclusionStrategy implements ExclusionStrategy {

	private Class classToExclude;

	public CustomExclusionStrategy(Class classToExclude) {
		this.classToExclude = classToExclude;
	}

	// This method is called for all fields. if the method returns false the
	// field is excluded from serialization
	//@Override
	public boolean shouldSkipField(FieldAttributes f) {
		if (f.getAnnotation(Country.class) == null)
			return false;

		return true;
	}

	// This method is called for all classes. If the method returns false the class is excluded.
	//@Override
	public boolean shouldSkipClass(Class<?> clazz) {
		if (clazz.equals(classToExclude))
			return true;
		return false;
	}

}
package model;

import java.util.List;
import java.util.Set;

import com.google.gson.annotations.Expose;

public class Employee {
	@Expose
	private String employeeId;
	@Expose
	private String firstName;
	private String middleName;
	@Expose
	private String lastName;
	@Expose
	private String designation;
	private int salary;
	@Expose
	private String permanentAddress;
	private String mailingAddress;
	@Country
	private String country;
	@Expose
	private String mobile;
	private Set<Education> educationDetail;
	private List<Experience> expericeDetail;

	@Override
	public String toString() {
		return "Employee [employeeId=" + employeeId + ", firstName=" + firstName + ", middleName=" + middleName
				+ ", lastName=" + lastName + ", designation=" + designation + ", salary=" + salary
				+ ", permanentAddress=" + permanentAddress + ", mailingAddress=" + mailingAddress + ", mobile=" + mobile
				+ ", educationDetail=" + educationDetail + ", expericeDetail=" + expericeDetail + "]";
	}

	public Employee(String employeeId, String firstName, String middleName, String lastName, String designation,
			int salary, String permanentAddress, String mailingAddress, String mobile, Set<Education> educationDetail,
			List<Experience> expericeDetail) {
		super();
		this.employeeId = employeeId;
		this.firstName = firstName;
		this.middleName = middleName;
		this.lastName = lastName;
		this.designation = designation;
		this.salary = salary;
		this.permanentAddress = permanentAddress;
		this.mailingAddress = mailingAddress;
		this.mobile = mobile;
		this.educationDetail = educationDetail;
		this.expericeDetail = expericeDetail;
	}
//Getter and setter of fields
	}

package model;

public class Education {
private String schoolOrCollegeName;
private String standard;
private String stream;
private double percentage;

@Override
public String toString() {
	return "Education [schoolOrCollegeName=" + schoolOrCollegeName + ", standard=" + standard + ", stream=" + stream
			+ ", percentage=" + percentage + "]";
}
public Education(String schoolOrCollegeName, String standard, String stream, double percentage) {
	super();
	this.schoolOrCollegeName = schoolOrCollegeName;
	this.standard = standard;
	this.stream = stream;
	this.percentage = percentage;
}
}
package model;

import java.util.Date;

public class Experience {
private String companyName;
private String designation;
private Date startDate;
private Date endDate;
private double salary;
public Experience(String companyName, String designation, Date startDate, Date endDate, double salary) {
	super();
	this.companyName = companyName;
	this.designation = designation;
	this.startDate = startDate;
	this.endDate = endDate;
	this.salary = salary;
}
@Override
public String toString() {
	return "Experience [companyName=" + companyName + ", designation=" + designation + ", startDate=" + startDate
			+ ", endDate=" + endDate + ", salary=" + salary + "]";
}
//getter and setter
}

Output

{
  "employeeId": "C123",
  "firstName": "Saurabh",
  "lastName": "Gupta",
  "designation": "Tech Lead",
  "permanentAddress": "Alpharetta,GA",
  "mobile": "1231231230"
}

Here in above JSON output for Employee class fields middleName, educationDetail and experienceDetail not printed because @Expose annotation was not given on that and by using CustomExlusionStartegy skiping serialization for fields country because it’s having @Country annotation as we remove in class for serialization CustomExclusionStrategy for @Country annotation.

Now in next example will discuss about.

How to parse JSON data token by token by using GSON/JsonToken/JsonReader?

How to do JSON pretty formatting and Null Serialization (GSON/GsonBuilder)


In previous example use GSON comes with simple JAVA API’s to convert JAVA object to/from JSON and here I will use GsonBuilder to print format JSON and serialize null object values also.

How to convert Java object to / from JSON by (GSON)

Pre-Requisite:

  • JAVA 8
  • Maven 3
  • GSON Jar as below.

GSON Dependency:

 <dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.2</version>
 </dependency>

Convert JAVA object to/from JSON

package gsonexamples;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import model.Employee;

public class GsonConvertJavaToJSON {

	public static void main(String[] args) {
		//Create GSON Object
		//Gson gson = new Gson();
Gson gson = new GsonBuilder().setPrettyPrinting().serializeNulls().create();
		Employee employee=getJavaObject();
		String json=gson.toJson(employee);

        System.out.println("Convert Java Object To JSON");
		System.out.println(json);

		System.out.println("Convert JSON To Java Object");
		employee=gson.fromJson(json,Employee.class);
		System.out.println(employee);

	}
	public static  Employee getJavaObject()
	{
		Employee employee=new Employee("C123","Saurabh" ,"Kumar","Gupta","Tech Lead",50000,"Alpharetta,GA","Dallas, TX","1231231230",null,null);
		return employee;
	}

}

  • GsonBuilder().setPrettyPrinting() :  This api is to generate pretty formatted JSON string.
  • GsonBuilder().searializeNulls() :  This api is to serialize null values in object.
  • GsonBuilder().create(): This api is to create GSON object to Java object to/from JSON.
package model;

import java.util.List;
import java.util.Set;

public class Employee {
private String employeeId;
private String firstName;
private String middleName;
private String lastName;
private String designation;
private int salary;
private String permanentAddress;
private String mailingAddress;
private String mobile;
private Set<Education> educationDetail;
private List<Experience> expericeDetail;

@Override
public String toString() {
	return "Employee [employeeId=" + employeeId + ", firstName=" + firstName + ", middleName=" + middleName
			+ ", lastName=" + lastName + ", designation=" + designation + ", salary=" + salary + ", permanentAddress="
			+ permanentAddress + ", mailingAddress=" + mailingAddress + ", mobile=" + mobile + ", educationDetail="
			+ educationDetail + ", expericeDetail=" + expericeDetail + "]";
}
public Employee(String employeeId, String firstName, String middleName, String lastName, String designation, int salary,
		String permanentAddress, String mailingAddress, String mobile, Set<Education> educationDetail,
		List<Experience> expericeDetail) {
	super();
	this.employeeId = employeeId;
	this.firstName = firstName;
	this.middleName = middleName;
	this.lastName = lastName;
	this.designation = designation;
	this.salary = salary;
	this.permanentAddress = permanentAddress;
	this.mailingAddress = mailingAddress;
	this.mobile = mobile;
	this.educationDetail = educationDetail;
	this.expericeDetail = expericeDetail;
}
//Getter and Setter
}

package model;

public class Education {
private String schoolOrCollegeName;
private String standard;
private String stream;
private double percentage;

@Override
public String toString() {
	return "Education [schoolOrCollegeName=" + schoolOrCollegeName + ", standard=" + standard + ", stream=" + stream
			+ ", percentage=" + percentage + "]";
}
public Education(String schoolOrCollegeName, String standard, String stream, double percentage) {
	super();
	this.schoolOrCollegeName = schoolOrCollegeName;
	this.standard = standard;
	this.stream = stream;
	this.percentage = percentage;
}
//getter and setter
}
package model;

import java.util.Date;

public class Experience {
private String companyName;
private String designation;
private Date startDate;
private Date endDate;
private double salary;
public Experience(String companyName, String designation, Date startDate, Date endDate, double salary) {
	super();
	this.companyName = companyName;
	this.designation = designation;
	this.startDate = startDate;
	this.endDate = endDate;
	this.salary = salary;
}
@Override
public String toString() {
	return "Experience [companyName=" + companyName + ", designation=" + designation + ", startDate=" + startDate
			+ ", endDate=" + endDate + ", salary=" + salary + "]";
}
//getter and setter
}

Output:

Convert Java Object To JSON
{
  "employeeId": "C123",
  "firstName": "Saurabh",
  "middleName": "Kumar",
  "lastName": "Gupta",
  "designation": "Tech Lead",
  "salary": 50000,
  "permanentAddress": "Alpharetta,GA",
  "mailingAddress": "Dallas, TX",
  "mobile": "1231231230",
  "educationDetail": null,
  "expericeDetail": null
}
<span 				data-mce-type="bookmark" 				id="mce_SELREST_start" 				data-mce-style="overflow:hidden;line-height:0" 				style="overflow:hidden;line-height:0" 			></span>
Convert JSON To Java Object
Employee [employeeId=C123, firstName=Saurabh, middleName=Kumar, lastName=Gupta, designation=Tech Lead, salary=50000, permanentAddress=Alpharetta,GA, mailingAddress=Dallas, TX, mobile=1231231230, educationDetail=null, expericeDetail=null]

In above JSON output is pretty formatted properly and  serialize null objects for education and experience. In next blog will explain about how to exclude fields while serializing/deserializing to/from JSON by GsonBuilder.

How to exclude fields from JSON while parsing by GSON/GsonBuilder?