GEODE-7694: fix pdx type lookup (#572)

- < operator should have used typeId, was using className which is NOT UNIQUE
- This should fix problems with __GEMFIRE_JSON PDX type
- fall back to comparing className when both typeIds are 0
- Local regions appear to operate with typeId == 0 for everything
- Local regions will still be broken for __GEMFIRE_JSON type, because className is the same for different types
diff --git a/cppcache/integration/test/CMakeLists.txt b/cppcache/integration/test/CMakeLists.txt
index 4c583ed..c2d77d3 100644
--- a/cppcache/integration/test/CMakeLists.txt
+++ b/cppcache/integration/test/CMakeLists.txt
@@ -25,6 +25,7 @@
   ExpirationTest.cpp
   FunctionExecutionTest.cpp
   PdxInstanceTest.cpp
+  PdxJsonTypeTest.cpp
   PdxSerializerTest.cpp
   RegionGetAllTest.cpp
   RegionPutAllTest.cpp
diff --git a/cppcache/integration/test/PdxJsonTypeTest.cpp b/cppcache/integration/test/PdxJsonTypeTest.cpp
new file mode 100644
index 0000000..e98eb48
--- /dev/null
+++ b/cppcache/integration/test/PdxJsonTypeTest.cpp
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <framework/Cluster.h>
+#include <framework/Gfsh.h>
+
+#include <future>
+#include <initializer_list>
+#include <iostream>
+#include <memory>
+#include <thread>
+
+#include <gtest/gtest.h>
+
+#include <geode/Cache.hpp>
+#include <geode/PdxInstanceFactory.hpp>
+#include <geode/PoolManager.hpp>
+#include <geode/RegionFactory.hpp>
+#include <geode/RegionShortcut.hpp>
+#include <geode/TypeRegistry.hpp>
+
+#include "CacheRegionHelper.hpp"
+#include "LocalRegion.hpp"
+#include "NestedPdxObject.hpp"
+#include "PdxType.hpp"
+
+namespace {
+using apache::geode::client::Cache;
+using apache::geode::client::CacheableKey;
+using apache::geode::client::CacheableString;
+using apache::geode::client::CacheRegionHelper;
+using apache::geode::client::IllegalStateException;
+using apache::geode::client::LocalRegion;
+using apache::geode::client::PdxFieldTypes;
+using apache::geode::client::PdxInstance;
+using apache::geode::client::PdxInstanceFactory;
+using apache::geode::client::PdxSerializable;
+using apache::geode::client::Region;
+using apache::geode::client::RegionShortcut;
+
+using PdxTests::Address;
+using PdxTests::PdxType;
+
+using testobject::ChildPdx;
+using testobject::ParentPdx;
+
+const std::string gemfireJsonClassName = "__GEMFIRE_JSON";
+
+std::shared_ptr<Region> setupRegion(Cache& cache) {
+  auto region = cache.createRegionFactory(RegionShortcut::PROXY)
+                    .setPoolName("default")
+                    .create("region");
+
+  return region;
+}
+
+TEST(PdxJsonTypeTest, testCreateTwoJsonInstances) {
+  Cluster cluster{LocatorCount{1}, ServerCount{1}};
+  cluster.start();
+  cluster.getGfsh()
+      .create()
+      .region()
+      .withName("region")
+      .withType("REPLICATE")
+      .execute();
+
+  auto cache = cluster.createCache();
+  auto region = setupRegion(cache);
+  auto pdxInstanceFactory =
+      cache.createPdxInstanceFactory(gemfireJsonClassName);
+
+  pdxInstanceFactory.writeString("foo", "bar");
+  auto pdxInstance = pdxInstanceFactory.create();
+
+  region->put("simpleObject", pdxInstance);
+
+  auto retrievedValue = region->get("simpleObject");
+
+  pdxInstance = std::dynamic_pointer_cast<PdxInstance>(retrievedValue);
+
+  EXPECT_FALSE(pdxInstance == nullptr);
+  EXPECT_TRUE(pdxInstance->hasField("foo"));
+  EXPECT_EQ(pdxInstance->getFieldType("foo"), PdxFieldTypes::STRING);
+  EXPECT_EQ(pdxInstance->getStringField("foo"), std::string{"bar"});
+
+  auto pdxInstanceFactory2 =
+      cache.createPdxInstanceFactory(gemfireJsonClassName);
+  pdxInstanceFactory2.writeInt("baz", 42);
+  pdxInstance = pdxInstanceFactory2.create();
+
+  region->put("anotherSimpleObject", pdxInstance);
+  retrievedValue = region->get("anotherSimpleObject");
+
+  pdxInstance = std::dynamic_pointer_cast<PdxInstance>(retrievedValue);
+
+  EXPECT_FALSE(pdxInstance == nullptr);
+  EXPECT_TRUE(pdxInstance->hasField("baz"));
+  EXPECT_EQ(pdxInstance->getFieldType("baz"), PdxFieldTypes::INT);
+  EXPECT_EQ(pdxInstance->getIntField("baz"), 42);
+}
+
+}  // namespace
diff --git a/cppcache/src/PdxType.cpp b/cppcache/src/PdxType.cpp
index 06df022..348acf4 100644
--- a/cppcache/src/PdxType.cpp
+++ b/cppcache/src/PdxType.cpp
@@ -557,7 +557,11 @@
 }
 
 bool PdxType::operator<(const PdxType& other) const {
-  return this->m_className < other.m_className;
+  auto typeIdLessThan = this->m_geodeTypeId < other.m_geodeTypeId;
+  auto typeIdsBothZero =
+      (this->m_geodeTypeId == 0) && (other.m_geodeTypeId == 0);
+  auto classnameLessThan = this->m_className < other.m_className;
+  return (typeIdLessThan || (typeIdsBothZero && classnameLessThan));
 }
 
 }  // namespace client