Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,28 @@ on:
branches: [ master ]

jobs:
build-scan:
name: SonarCloud Scan
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'temurin'
cache: maven

- name: Build/Test & SonarCloud Scan
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
if: env.SONAR_TOKEN != ''
run: mvn -B clean verify -Pcoverage,sonar -Dsonar.token=${{ secrets.SONAR_TOKEN }}

build-test:
name: Build & Test - JDK ${{ matrix.java }} on ${{ matrix.os }}
strategy:
Expand Down
76 changes: 71 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ The `DotPathQL` is the core component of this project that allows you to extract
- 📋 **Collection Handling**: Process Lists, Arrays, and other Collections
- 🗺️ **Map Support**: Handle both simple and complex Map structures
- 📝 **Record & POJO Support**: Works with Java Records and traditional classes
- 📄 **JSON Output**: Convert results to pretty-formatted or compact JSON strings
- 🔒 **Private Field Access**: Can access private fields when getters aren't available (filtering only)
- 🚀 **Performance Optimized**: Efficient reflection-based property access

Expand Down Expand Up @@ -174,23 +175,88 @@ List<String> reportFields = List.of(
);
```

## JSON Output

Convert your filtered or excluded results to JSON format using the built-in `toJson` method. This feature supports both pretty-formatted (indented) and compact (single-line) output.

### Pretty JSON

```java
var dotPathQL = new DotPathQL();
var result = dotPathQL.filter(userObject, List.of(
"username",
"address.street",
"address.city",
"orders.products.name"
));

// Pretty formatted JSON with 2-space indentation
String prettyJson = dotPathQL.toJson(result, true);
//or
String prettyJson = dotPathQL.toJson(result, 4); // Custom indentation level
```

**Output:**
```json
{
"username": "john_doe",
"address": {
"street": "123 Main St",
"city": "Springfield"
},
"orders": [
{
"products": [
{
"name": "Laptop"
},
{
"name": "Mouse"
}
]
}
]
}
```

### Compact JSON

```java
// Compact single-line JSON
String compactJson = dotPathQL.toJson(result, false);
System.out.println(compactJson);
```

**Output:**
```json
{"username": "john_doe", "address": {"street": "123 Main St", "city": "Springfield"}, "orders": [{"products": [{"name": "Laptop"}, {"name": "Mouse"}]}]}
```

## Helper Utilities

You can also easy access the map result using the `DotPathQL` utility methods:

### Quick Access Methods

```java
// Step 1
var dotPathQL = new DotPathQL();
var result = dotPathQL.filter(userObject, List.of(
DotPathQL dotPathQL = new DotPathQL();
Map<String, Object> result = dotPathQL.filter(userObject, List.of(
"address",
"friendList",
"games"
));

// Step 2: Accessing the result
var address = dotPathQL.mapFrom(result, "address");
var friendList = dotPathQL.listFrom(result, "friendList");
var games = dotPathQL.arrayFrom(result, "games");
Map<String, Object> address = dotPathQL.mapFrom(result, "address");
List<Map<String, Object>> friendList = dotPathQL.listFrom(result, "friendList");
Object[] games = dotPathQL.arrayFrom(result, "games");
```

### Map objects

```java
Map<String, Object> userMap = dotPathQL.toMap(userObject);
```

## Technical Requirements
Expand Down
72 changes: 72 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,19 @@
<lombok.version>1.18.30</lombok.version>

<!-- plugins -->
<jacoco-maven-plugin.version>0.8.13</jacoco-maven-plugin.version>
<sonar-maven-plugin.version>3.11.0.3922</sonar-maven-plugin.version>
<maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version>
<maven-source-plugin.version>3.3.1</maven-source-plugin.version>
<maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version>
<maven-javadoc-plugin.version>3.11.2</maven-javadoc-plugin.version>
<maven-gpg-plugin.version>3.2.8</maven-gpg-plugin.version>
<central-publishing-maven-plugin.version>0.8.0</central-publishing-maven-plugin.version>

<!-- sonar -->
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<sonar.language>java</sonar.language>
</properties>

<dependencies>
Expand All @@ -81,6 +88,61 @@
</dependencies>

<profiles>
<profile>
<id>coverage</id>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>sonar</id>
<properties>
<sonar.projectName>dot-path-ql</sonar.projectName>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
<sonar.organization>trackerforce</sonar.organization>
<sonar.projectKey>trackerforce_dot-path-ql</sonar.projectKey>
<sonar.moduleKey>${project.groupId}:${project.artifactId}</sonar.moduleKey>
</properties>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>sonar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>sign</id>
<build>
Expand Down Expand Up @@ -139,6 +201,16 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>${sonar-maven-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-maven-plugin.version}</version>
</plugin>
</plugins>
</pluginManagement>

Expand Down
39 changes: 37 additions & 2 deletions src/main/java/io/github/trackerforce/DotPathQL.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
import java.util.Map;

/**
* Utility class for filtering objects based on specified paths.
* It supports nested properties, collections, and arrays.
* API for filtering and excluding properties from objects using dot paths.
*
* @author petruki
* @since 2025-08-02
Expand All @@ -16,13 +15,15 @@ public class DotPathQL {

private final PathCommon pathFilter;
private final PathCommon pathExclude;
private final PathPrinter pathPrinter;

/**
* Constructs a DotPathQL instance with an empty list of default filter paths.
*/
public DotPathQL() {
pathFilter = new PathFilter();
pathExclude = new PathExclude();
pathPrinter = new PathPrinter(2);
}

/**
Expand Down Expand Up @@ -54,6 +55,17 @@ public <T> Map<String, Object> exclude(T source, List<String> excludePaths) {
return pathExclude.run(source, excludePaths);
}

/**
* Converts the source object to a map representation.
*
* @param <T> the type of the source object
* @param source the source object to convert
* @return a map containing all properties of the source object
*/
public <T> Map<String, Object> toMap(T source) {
return exclude(source, Collections.emptyList());
}

/**
* Extracts a map from the source map based on the specified property.
*
Expand Down Expand Up @@ -120,6 +132,29 @@ public void addDefaultExcludePaths(List<String> paths) {
pathExclude.addDefaultPaths(paths);
}

/**
* Converts the given sourceMap to a JSON string representation with optional formatting.
*
* @param sourceMap the source map to convert to JSON
* @param indentSize the number of spaces to use for indentation
* @return a JSON string representation of the object
*/
public String toJson(Map<String, Object> sourceMap, int indentSize) {
pathPrinter.setIndentSize(indentSize);
return toJson(sourceMap, true);
}

/**
* Converts the given sourceMap to a JSON string representation.
*
* @param sourceMap the source map to convert to JSON
* @param prettier if true, formats with proper indentation; if false, compact single-line format
* @return a JSON string representation of the object
*/
public String toJson(Map<String, Object> sourceMap, boolean prettier) {
return pathPrinter.toJson(sourceMap, prettier);
}

private boolean isInvalid(Map<String, Object> source, String property) {
return source == null || property == null || property.isEmpty() || !source.containsKey(property);
}
Expand Down
Loading