Description: adapting code to use Debian package libjson-java instead of the
 non-free org.json.
 - Beware, in libjson-java, JSONObject.put returns the added object, not the
 JSONObject. Calls to put thus cannot be chained.
 - In JSONArray there is no put method, using add instead.
 - Error messages are not exactly the same in org.json and libjson-java.
 - Ignoring default excludes when parsing json string to avoid skipping a
 field named "class".
Author: Pierre Gruet <pgt@debian.org>
Forwarded: not-needed
Last-Update: 2024-12-26

--- a/src/main/java/htsjdk/beta/io/bundle/BundleJSON.java
+++ b/src/main/java/htsjdk/beta/io/bundle/BundleJSON.java
@@ -4,9 +4,9 @@
 import htsjdk.io.IOPath;
 import htsjdk.samtools.util.Log;
 import htsjdk.utils.ValidationUtils;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
+import org.kordamp.json.JSONArray;
+import org.kordamp.json.JSONException;
+import org.kordamp.json.JSONObject;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -49,12 +49,12 @@
         ValidationUtils.validateArg(
                 !bundle.getPrimaryContentType().equals(JSON_PROPERTY_PRIMARY),
                 "Primary content type cannot be named 'primary'");
-        final JSONObject schemaMap = new JSONObject()
-                .put(JSON_PROPERTY_SCHEMA_NAME, JSON_SCHEMA_NAME)
-                .put(JSON_PROPERTY_SCHEMA_VERSION, JSON_SCHEMA_VERSION);
-        final JSONObject outerJSON = new JSONObject()
-            .put(JSON_PROPERTY_SCHEMA, schemaMap)
-            .put(JSON_PROPERTY_PRIMARY, bundle.getPrimaryContentType());
+        JSONObject schemaMap = new JSONObject();
+        schemaMap.put(JSON_PROPERTY_SCHEMA_NAME, JSON_SCHEMA_NAME);
+        schemaMap.put(JSON_PROPERTY_SCHEMA_VERSION, JSON_SCHEMA_VERSION);
+        JSONObject outerJSON = new JSONObject();
+        outerJSON.put(JSON_PROPERTY_SCHEMA, schemaMap);
+        outerJSON.put(JSON_PROPERTY_PRIMARY, bundle.getPrimaryContentType());
 
         bundle.forEach(bundleResource -> {
             final Optional<IOPath> resourcePath = bundleResource.getIOPath();
@@ -63,7 +63,8 @@
             }
 
             // generate JSON for each bundle resource
-            final JSONObject resourceJSON = new JSONObject().put(JSON_PROPERTY_PATH, resourcePath.get().getURIString());
+            JSONObject resourceJSON = new JSONObject();
+            resourceJSON.put(JSON_PROPERTY_PATH, resourcePath.get().getURIString());
             if (bundleResource.getFileFormat().isPresent()) {
                 resourceJSON.put(JSON_PROPERTY_FORMAT, bundleResource.getFileFormat().get());
             }
@@ -114,7 +115,7 @@
         ValidationUtils.nonEmpty(jsonString, "JSON string");
         ValidationUtils.nonNull(ioPathConstructor, "IOPath-derived class constructor");
         try {
-            return toBundle(new JSONObject(jsonString), ioPathConstructor);
+            return toBundle(JSONObject.fromObject(jsonString), ioPathConstructor);
         } catch (JSONException | UnsupportedOperationException e) {
             // see if the user provided a collection instead of a single bundle, and if so, present it as
             // a Bundle as long as it only contains one BundleResource
@@ -152,7 +153,7 @@
 
         final List<Bundle> bundles = new ArrayList<>();
         try {
-            final JSONArray jsonArray = new JSONArray(jsonString);
+            final JSONArray jsonArray = JSONArray.fromObject(jsonString);
             jsonArray.forEach(element -> {
                 if (! (element instanceof JSONObject jsonObject)) {
                     throw new IllegalArgumentException(
@@ -164,7 +165,7 @@
         } catch (JSONException | UnsupportedOperationException e) {
             // see if the user provided a single bundle instead of a collection, if so, wrap it up as a collection
             try {
-                bundles.add(toBundle(new JSONObject(jsonString), ioPathConstructor));
+                bundles.add(toBundle(JSONObject.fromObject(jsonString), ioPathConstructor));
             } catch (JSONException | UnsupportedOperationException e2) {
                 throw new IllegalArgumentException(
                         String.format("JSON can be interpreted neither as an individual bundle (%s) nor as a bundle collection (%s)",
@@ -234,7 +235,7 @@
         jsonResources.keySet().forEach(key -> {
             if (!TOP_LEVEL_PROPERTIES.contains(key)) {
                 if (jsonResources.get(key) instanceof JSONObject resourceObject) {
-                    bundleResources.add(toBundleResource(key, resourceObject, ioPathConstructor));
+                    bundleResources.add(toBundleResource((String)(key), resourceObject, ioPathConstructor));
                 } else {
                     throw new IllegalArgumentException(
                             String.format("Bundle resources may contain only BundleResource objects, found %s", key));
--- a/src/main/java/htsjdk/samtools/util/htsget/HtsgetErrorResponse.java
+++ b/src/main/java/htsjdk/samtools/util/htsget/HtsgetErrorResponse.java
@@ -1,7 +1,7 @@
 package htsjdk.samtools.util.htsget;
 
 
-import org.json.JSONObject;
+import org.kordamp.json.JSONObject;
 
 /**
  * Class allowing deserialization from json htsget error response, as defined in https://samtools.github.io/hts-specs/htsget.html
@@ -32,7 +32,7 @@
     }
 
     public static HtsgetErrorResponse parse(final String s) {
-        final JSONObject j = new JSONObject(s);
+        final JSONObject j = JSONObject.fromObject(s);
         final JSONObject htsget = j.optJSONObject("htsget");
         if (htsget == null) {
             throw new IllegalStateException(new HtsgetMalformedResponseException("No htsget key found in response"));
--- a/src/main/java/htsjdk/samtools/util/htsget/HtsgetPOSTRequest.java
+++ b/src/main/java/htsjdk/samtools/util/htsget/HtsgetPOSTRequest.java
@@ -3,8 +3,8 @@
 import htsjdk.samtools.SAMRecord;
 import htsjdk.samtools.util.Locatable;
 import htsjdk.samtools.util.RuntimeIOException;
-import org.json.JSONArray;
-import org.json.JSONObject;
+import org.kordamp.json.JSONArray;
+import org.kordamp.json.JSONObject;
 
 import java.io.IOException;
 import java.net.HttpURLConnection;
@@ -146,19 +146,19 @@
         if (!this.fields.isEmpty()) {
             postBody.put(
                 "fields",
-                new JSONArray(this.getFields().stream()
+                JSONArray.fromObject(this.getFields().stream()
                     .map(HtsgetRequestField::toString)
                     .toArray())
             );
         }
         if (!this.tags.isEmpty()) {
-            postBody.put("tags", new JSONArray(this.getTags().toArray()));
+            postBody.put("tags", JSONArray.fromObject(this.getTags().toArray()));
         }
         if (!this.notags.isEmpty()) {
-            postBody.put("notags", new JSONArray(this.getNoTags().toArray()));
+            postBody.put("notags", JSONArray.fromObject(this.getNoTags().toArray()));
         }
         if (!this.intervals.isEmpty()) {
-            postBody.put("regions", new JSONArray(
+            postBody.put("regions", JSONArray.fromObject(
                 this.intervals.stream()
                     .map(interval -> {
                         final JSONObject intervalJson = new JSONObject();
--- a/src/main/java/htsjdk/samtools/util/htsget/HtsgetResponse.java
+++ b/src/main/java/htsjdk/samtools/util/htsget/HtsgetResponse.java
@@ -1,8 +1,9 @@
 package htsjdk.samtools.util.htsget;
 
 import htsjdk.samtools.util.RuntimeIOException;
-import org.json.JSONArray;
-import org.json.JSONObject;
+import org.kordamp.json.JsonConfig;
+import org.kordamp.json.JSONArray;
+import org.kordamp.json.JSONObject;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
@@ -126,9 +127,9 @@
             final JSONObject headersJson = blockJson.optJSONObject("headers");
             final Map<String, String> headers = headersJson == null
                 ? null
-                : headersJson.toMap().entrySet().stream()
+                : ((Set<Map.Entry<String, Object> >)(headersJson.entrySet())).stream()
                 .collect(Collectors.toMap(
-                    Map.Entry::getKey,
+                    Map.Entry<String, Object>::getKey,
                     e -> e.getValue().toString()
                 ));
 
@@ -167,7 +168,9 @@
      * @return parsed HtsgetResponse object
      */
     public static HtsgetResponse parse(final String s) {
-        final JSONObject j = new JSONObject(s);
+        JsonConfig cfgJson = new JsonConfig();
+        cfgJson.setIgnoreDefaultExcludes(true); //Accept "class" as a field name!
+        final JSONObject j = JSONObject.fromObject(s, cfgJson);
         final JSONObject htsget = j.optJSONObject("htsget");
         if (htsget == null) {
             throw new HtsgetMalformedResponseException("No htsget key found in response");
@@ -181,7 +184,7 @@
             throw new HtsgetMalformedResponseException("No urls field found in Htsget Response");
         }
 
-        final List<Block> blocks = IntStream.range(0, blocksJson.length())
+        final List<Block> blocks = IntStream.range(0, blocksJson.size())
             .mapToObj(blocksJson::getJSONObject)
             .map(Block::parse)
             .collect(Collectors.toList());
--- a/src/test/java/htsjdk/beta/io/bundle/BundleJSONTest.java
+++ b/src/test/java/htsjdk/beta/io/bundle/BundleJSONTest.java
@@ -3,7 +3,7 @@
 import htsjdk.HtsjdkTest;
 import htsjdk.io.HtsPath;
 import htsjdk.io.IOPath;
-import org.json.JSONObject;
+import org.kordamp.json.JSONObject;
 import org.testng.Assert;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
@@ -193,7 +193,7 @@
     public void testRoundTripJSONSingle(final String jsonString, final String primaryKey, final List<BundleResource> resources) {
         final Bundle bundleFromResources = new Bundle(primaryKey, resources);
         final String actualJSONString = BundleJSON.toJSON(bundleFromResources);
-        Assert.assertEquals(actualJSONString, new JSONObject(jsonString).toString(1));
+        Assert.assertEquals(JSONObject.fromObject(actualJSONString), JSONObject.fromObject(jsonString));
 
         // now recreate the bundle from JSON
         final Bundle bundleFromJSON = BundleJSON.toBundle(jsonString);
@@ -279,7 +279,7 @@
                 {"", "The string is empty"},
 
                 // missing schema entirely
-                {"{}", "[\"schema\"] not found"},
+                {"{}", "null object"},
 
                 // missing schema name
                 {
@@ -378,7 +378,7 @@
                             BundleJSON.JSON_SCHEMA_VERSION,
                             BundleResourceType.CT_ALIGNED_READS, BundleResourceType.FMT_READS_BAM,
                             BundleResourceType.CT_ALIGNED_READS),
-                    "Expected a ':' after a key at 36 [character 19 line 3]"
+                    "Expected a ':' after a key at"
                 },
 
                 // missing enclosing {} -> UnsupportedOperationException (no text message)
@@ -389,7 +389,7 @@
                         "schemaVersion":"%s",
                     }
                     """.formatted(BundleJSON.JSON_SCHEMA_VERSION),
-                    "A JSONObject text must begin with '{' at 1 [character 2 line 1]",
+                    "A JSONObject text must begin with '{' at",
                 },
         };
     }
--- a/src/test/java/htsjdk/samtools/util/HtsgetRequestUnitTest.java
+++ b/src/test/java/htsjdk/samtools/util/HtsgetRequestUnitTest.java
@@ -2,8 +2,8 @@
 
 import htsjdk.HtsjdkTest;
 import htsjdk.samtools.util.htsget.*;
-import org.json.JSONArray;
-import org.json.JSONObject;
+import org.kordamp.json.JSONArray;
+import org.kordamp.json.JSONObject;
 import org.testng.Assert;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
@@ -123,27 +123,27 @@
         Assert.assertEquals(postBody.getString("class"), "header");
 
         Assert.assertEqualsNoOrder(
-            postBody.getJSONArray("fields").toList().stream().map(Object::toString).toArray(String[]::new),
+            JSONArray.toList(postBody.getJSONArray("fields")).stream().map(Object::toString).toArray(String[]::new),
             new String[]{"QNAME", "CIGAR"}
         );
         Assert.assertEqualsNoOrder(
-            postBody.getJSONArray("tags").toList().stream().map(Object::toString).toArray(String[]::new),
+            JSONArray.toList(postBody.getJSONArray("tags")).stream().map(Object::toString).toArray(String[]::new),
             new String[]{"tag1", "tag3"}
         );
         Assert.assertEqualsNoOrder(
-            postBody.getJSONArray("notags").toList().stream().map(Object::toString).toArray(String[]::new),
+            JSONArray.toList(postBody.getJSONArray("notags")).stream().map(Object::toString).toArray(String[]::new),
             new String[]{"tag2"}
         );
 
-        final JSONArray expectedRegions = new JSONArray()
-            .put(new JSONObject("{referenceName: \"chr1\", start: 0, end: 16}"))
-            .put(new JSONObject("{referenceName: \"chr1\", start: 16, end: 32}"))
-            .put(new JSONObject("{referenceName: \"chrM\", start: 0, end: 16}"))
-            .put(new JSONObject("{referenceName: \"chrM\", start: 16, end: 32}"));
+        JSONArray expectedRegions = new JSONArray();
+        expectedRegions.add(JSONObject.fromObject("{referenceName: \"chr1\", start: 0, end: 16}"));
+        expectedRegions.add(JSONObject.fromObject("{referenceName: \"chr1\", start: 16, end: 32}"));
+        expectedRegions.add(JSONObject.fromObject("{referenceName: \"chrM\", start: 0, end: 16}"));
+        expectedRegions.add(JSONObject.fromObject("{referenceName: \"chrM\", start: 16, end: 32}"));
 
         Assert.assertEqualsNoOrder(
-            postBody.getJSONArray("regions").toList(),
-            expectedRegions.toList()
+            JSONArray.toList(postBody.getJSONArray("regions")).toArray(),
+            JSONArray.toList(expectedRegions).toArray()
         );
     }
-}
\ No newline at end of file
+}
