diff --git a/README.md b/README.md index cc9ec49..69163c7 100644 --- a/README.md +++ b/README.md @@ -190,6 +190,19 @@ for (DotenvEntry e : dotenv.entries()) { .load(); ``` +### *optional* `ignoreEmpty` + +* Treat empty or blank values as `null`. + + **example** + + ```java + Dotenv + .configure() + .ignoreEmpty() + .load(); + ``` + ### *optional* `systemProperties` * Load environment variables into System properties, thus making all environment variables accessible via `System.getProperty(...)` diff --git a/src/main/java/io/github/cdimascio/dotenv/DotenvBuilder.java b/src/main/java/io/github/cdimascio/dotenv/DotenvBuilder.java index c7b025c..136eb9a 100644 --- a/src/main/java/io/github/cdimascio/dotenv/DotenvBuilder.java +++ b/src/main/java/io/github/cdimascio/dotenv/DotenvBuilder.java @@ -15,6 +15,7 @@ public class DotenvBuilder { private String filename = ".env"; private String directoryPath = "./"; private boolean systemProperties = false; + private boolean ignoreEmpty = false; private boolean throwIfMissing = true; private boolean throwIfMalformed = true; @@ -37,6 +38,15 @@ public DotenvBuilder filename(final String name) { return this; } + /** + * Returns `null` for empty or blank values. + * @return this {@link DotenvBuilder} + */ + public DotenvBuilder ignoreEmpty() { + ignoreEmpty = true; + return this; + } + /** * Does not throw an exception when .env is missing. * @return this {@link DotenvBuilder} @@ -70,10 +80,12 @@ public DotenvBuilder systemProperties() { * @throws DotenvException when an error occurs */ public Dotenv load() throws DotenvException { - final var reader = new DotenvParser( - new DotenvReader(directoryPath, filename), - throwIfMissing, throwIfMalformed); - final List env = reader.parse(); + DotenvParser reader = new DotenvParser( + new DotenvReader(directoryPath, filename), + ignoreEmpty, + throwIfMissing, + throwIfMalformed); + List env = reader.parse(); if (systemProperties) { env.forEach(it -> System.setProperty(it.getKey(), it.getValue())); } diff --git a/src/main/java/io/github/cdimascio/dotenv/internal/DotenvParser.java b/src/main/java/io/github/cdimascio/dotenv/internal/DotenvParser.java index c244a7b..a3913fc 100644 --- a/src/main/java/io/github/cdimascio/dotenv/internal/DotenvParser.java +++ b/src/main/java/io/github/cdimascio/dotenv/internal/DotenvParser.java @@ -31,6 +31,7 @@ public class DotenvParser { private static final Pattern DOTENV_ENTRY_REGEX = Pattern.compile("^\\s*([\\w.\\-]+)\\s*(=)\\s*(['][^']*[']|[\"][^\"]*[\"]|[^#]*)?\\s*(#.*)?$"); //"^\\s*([\\w.\\-]+)\\s*(=)\\s*([^#]*)?\\s*(#.*)?$"); // ^\s*([\w.\-]+)\s*(=)\s*([^#]*)?\s*(#.*)?$ private final DotenvReader reader; + private final boolean ignoreEmtpy; private final boolean throwIfMissing; private final boolean throwIfMalformed; @@ -41,13 +42,14 @@ public class DotenvParser { /** * Creates a dotenv parser - * - * @param reader the dotenv reader - * @param throwIfMissing if true, throws when the .env file is missing + * @param reader the dotenv reader + * @param ignoreEmpty if true, returns `null` for empty or blank values + * @param throwIfMissing if true, throws when the .env file is missing * @param throwIfMalformed if true, throws when the .env file is malformed */ - public DotenvParser(final DotenvReader reader, final boolean throwIfMissing, final boolean throwIfMalformed) { + public DotenvParser(DotenvReader reader, boolean ignoreEmpty, boolean throwIfMissing, boolean throwIfMalformed) { this.reader = reader; + this.ignoreEmtpy = ignoreEmpty; this.throwIfMissing = throwIfMissing; this.throwIfMalformed = throwIfMalformed; } @@ -82,6 +84,7 @@ public List parse() throws DotenvException { currentEntry += "\n"; continue; } + if (!QuotedStringValidator.isValid(entry.getValue())) { if (throwIfMalformed) throw new DotenvException("Malformed entry, unmatched quotes " + line); @@ -90,6 +93,11 @@ public List parse() throws DotenvException { } final var key = entry.getKey(); value = QuotedStringValidator.stripQuotes(entry.getValue()); + + if (value.isEmpty() && ignoreEmtpy) { + continue; + } + entries.add(new DotenvEntry(key, value)); currentEntry = ""; } diff --git a/src/test/java/tests/DotenvTests.java b/src/test/java/tests/DotenvTests.java index a8e5b30..8ad6336 100644 --- a/src/test/java/tests/DotenvTests.java +++ b/src/test/java/tests/DotenvTests.java @@ -9,7 +9,11 @@ import java.util.HashMap; import java.util.Map; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + class DotenvTests { private Map envVars; @@ -102,7 +106,17 @@ void configureWithIgnoreMissingAndMalformed() { assertNotNull(dotenv.get("PATH")); } - @Test + @Test + void configureWithIgnoreMalformedAndEmpty() { + Dotenv dotenv = Dotenv.configure() + .ignoreIfMalformed() + .ignoreEmpty() + .load(); + + assertNull(dotenv.get("WITHOUT_VALUE")); + } + + @Test void malformedWithUncloseQuote() { final var dotenv = Dotenv.configure() .directory("/unclosed.quote")