json-view icon indicating copy to clipboard operation
json-view copied to clipboard

How to exclude fields of a referance object of same class

Open Devlad91 opened this issue 8 years ago • 1 comments

This is a great library ,I am using this library for a while now (since 0.12-SNAPSHOT) , and it is working like a charm. (At present i am using 0.16-SNAPSHOT) Recently I am facing a problem with my one of the Use cases, let me place my code first

# User class

public class User {

    private String name;
    private String emailId;
    private String mobileNo;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmailId() {
        return emailId;
    }

    public void setEmailId(String emailId) {
        this.emailId = emailId;
    }

    public String getMobileNo() {
        return mobileNo;
    }

    public void setMobileNo(String mobileNo) {
        this.mobileNo = mobileNo;
    }

}

# ScreenInfoPojo class

public class ScreenInfoPojo {

    private Long id;
    private String name;
    private ScreenInfoPojo parentScreen;
    private User createdBy;
    private User lastUpdatedBy;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ScreenInfoPojo getParentScreen() {
        return parentScreen;
    }

    public void setParentScreen(ScreenInfoPojo parentScreen) {
        this.parentScreen = parentScreen;
    }

    

    public User getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(User createdBy) {
        this.createdBy = createdBy;
    }

    public User getLastUpdatedBy() {
        return lastUpdatedBy;
    }

    public void setLastUpdatedBy(User lastUpdatedBy) {
        this.lastUpdatedBy = lastUpdatedBy;
    } 

# Run code

public class TestMain {
    public static void main(String[] args) throws JsonProcessingException {
        User user=new User();
        user.setName("ABC");
        user.setEmailId("[email protected]");
        user.setMobileNo("123456789");
        
        ScreenInfoPojo screen1=new ScreenInfoPojo();
        screen1.setId(1l);
        screen1.setName("Screen1");
        screen1.setCreatedBy(user);
        screen1.setLastUpdatedBy(user);
        
        ScreenInfoPojo screen2=new ScreenInfoPojo();
        screen2.setId(2l);
        screen2.setName("Screen2");
        screen2.setParentScreen(Screen1);
        screen2.setCreatedBy(user);
        screen2.setLastUpdatedBy(user);
        
        ScreenInfoPojo screen3=new ScreenInfoPojo();
        screen3.setId(3l);
        screen3.setName("Screen3");
        screen3.setParentScreen(Screen2);
        screen3.setCreatedBy(user);
        screen3.setLastUpdatedBy(user);
        
        ScreenInfoPojo screen4=new ScreenInfoPojo();
        screen4.setId(4l);
        screen4.setName("Screen4");
        screen4.setParentScreen(Screen3);
        screen4.setCreatedBy(user);
        screen4.setLastUpdatedBy(user);
        
        List<ScreenInfoPojo> screens=new ArrayList<>();
        screens.add(screen1);
        screens.add(screen2);
        screens.add(screen3);
        screens.add(screen4);
        
        ObjectMapper mapper = new ObjectMapper().registerModule(new JsonViewModule());
        String json = mapper.writeValueAsString(JsonView.with(screens).onClass(ScreenInfoPojo.class, Match.match()
                .exclude("*")
                .include("id","name","createdBy.name","lastUpdatedBy.mobileNo","parentScreen.id")));
        System.out.println("json"+json);
    }    

# Result

[{
	"id": 1,
	"name": "Screen1",
	"parentScreen": null,
	"createdBy": {
		"name": "ABC"
	},
	"lastUpdatedBy": {
		"mobileNo": "123456789"
	}
}, {
	"id": 2,
	"name": "Screen2",
	"parentScreen": {
		"id": 1,
		"name": "Screen1",
		"parentScreen": null,
		"createdBy": {},
		"lastUpdatedBy": {}
	},
	"createdBy": {
		"name": "ABC"
	},
	"lastUpdatedBy": {
		"mobileNo": "123456789"
	}
}, {
	"id": 3,
	"name": "Screen3",
	"parentScreen": {
		"id": 2,
		"name": "Screen2",
		"parentScreen": {
			"id": 1,
			"name": "Screen1",
			"parentScreen": null,
			"createdBy": {},
			"lastUpdatedBy": {}
		},
		"createdBy": {},
		"lastUpdatedBy": {}
	},
	"createdBy": {
		"name": "ABC"
	},
	"lastUpdatedBy": {
		"mobileNo": "123456789"
	}
}, {
	"id": 4,
	"name": "Screen4",
	"parentScreen": {
		"id": 3,
		"name": "Screen3",
		"parentScreen": {
			"id": 2,
			"name": "Screen2",
			"parentScreen": {
				"id": 1,
				"name": "Screen1",
				"parentScreen": null,
				"createdBy": {},
				"lastUpdatedBy": {}
			},
			"createdBy": {},
			"lastUpdatedBy": {}
		},
		"createdBy": {},
		"lastUpdatedBy": {}
	},
	"createdBy": {
		"name": "ABC"
	},
	"lastUpdatedBy": {
		"mobileNo": "123456789"
	}
}]




#Expected Result

[{
	"id": 1,
	"name": "Screen1",
	"parentScreen": null,
	"createdBy": {
		"name": "ABC"
	},
	"lastUpdatedBy": {
		"mobileNo": "123456789"
	}
}, {
	"id": 2,
	"name": "Screen2",
	"parentScreen": {
		"id": 1
	},
	"createdBy": {
		"name": "ABC"
	},
	"lastUpdatedBy": {
		"mobileNo": "123456789"
	}
}, {
	"id": 3,
	"name": "Screen3",
	"parentScreen": {
		"id": 2
	},
	"createdBy": {
		"name": "ABC"
	},
	"lastUpdatedBy": {
		"mobileNo": "123456789"
	}
}, {
	"id": 4,
	"name": "Screen4",
	"parentScreen": {
		"id": 3
	},
	"createdBy": {
		"name": "ABC"
	},
	"lastUpdatedBy": {
		"mobileNo": "123456789"
	}
}]

#Problem In my use case I have a class ScreenInfoPojo which refers to same class as parentScreen , I am trying to fetch specific field/fields of parent ( "parentScreen.id") instate I am getting all fields that I have defined on child/target Object ("id","name","createdBy.name","lastUpdatedBy.mobileNo","parentScreen.id") and parent response is again recursive ! One thing i observed that It is only happening in case of a class has its own reference , I placed User class reference as two different field createdBy and lastUpdatedBy and tried to fetch "name" and "mobileNo" respectively worked just fine. Can you suggest any solution for this problem?

Thanks

Devlad91 avatar May 18 '17 09:05 Devlad91

So this isn't possible in the latest release, for good reason. There are two ways that patterns can be matched: by explicit class association and by the dot-path. In the current implementation, the class matcher is always chosen first because it's explicitly detailing what fields on the class to match.

However, in your case it's somewhat problematic. To support this, I've added a behavior selector at the JsonViewModule level and the JsonView level. It will default to the current behavior (CLASS_FIRST), but you can optionally set it to PATH_FIRST which should do what you want.

Check out the test case for this: https://github.com/monitorjbl/json-view/blob/master/json-view/src/test/java/com/monitorjbl/json/JsonViewSerializerTest.java#L868.

monitorjbl avatar Jun 20 '17 01:06 monitorjbl