docs: @SuppressWarnings("unchecked")
      private static JSONArtrifactPair findFieldsToSerialize(Object o) {
          // if the object is a list, we'll return a JsonArray, containing each
          // thing in the List.
          if (o instanceof Collection) {
              Collection<? extends Object> listOfO = (Collection<? extends Object>) o;
  
              JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
              for (Object listObject : listOfO) {
                  //currently, we support lists of strings, or lists of POJOs.
                  if (listObject instanceof String) {
                      arrayBuilder.add((String) listObject);
                  } else if (listObject.getClass().getName().startsWith(DATA_MODEL_PACKAGE)) {
                      arrayBuilder.add(findFieldsToSerialize(listObject).mainObject);
                  } else {
                      throw new IllegalStateException("Data Model Error: serialization only supported for Collections of String, or other Data Model elements");
                  }
              }
  
              JsonArray result = arrayBuilder.build();
              return new JSONArtrifactPair(result, null);
          }
  
          // object wasn't a collection.. better see what we can do with it.
          JsonObjectBuilder mainObjectBuilder = Json.createObjectBuilder();
          SortedMap<String, Method> gettersFromO = new TreeMap<String, Method>();
          Class<? extends Object> classOfO = o.getClass();
  
          // See if we have any breaking changes that need to go into a separate object
          JsonObjectBuilder incompatibleFieldsObjectBuilder = null;
          Collection<String> fieldsToPutInIncompatibleObject = null;
          boolean haveIncompatibleFields = false;
          if (HasBreakingChanges.class.isAssignableFrom(classOfO)) {
              fieldsToPutInIncompatibleObject = ((HasBreakingChanges) o).attributesThatCauseBreakingChanges();
              if (!fieldsToPutInIncompatibleObject.isEmpty()) {
                  incompatibleFieldsObjectBuilder = Json.createObjectBuilder();
                  haveIncompatibleFields = true;
              }
          }
  
          for (Method methodFromO : classOfO.getMethods()) {
              if (methodFromO.getName().startsWith("get") && methodFromO.getName().length() > 3 && methodFromO.getParameterTypes().length == 0) {
                  Method old;
                  if ((old = gettersFromO.put(methodFromO.getName(), methodFromO)) != null) {
                      throw new IllegalStateException("Data Model Error: duplicate getter for "
                                                      + methodFromO + "(" + old + ") on "
                                                      + o.getClass().getName());
                  }
              }
          }
  
          for (Map.Entry<String, Method> entry : gettersFromO.entrySet()) {
  
              String getterName = entry.getKey();
  
              //not all getters are really for us ;p
              if ("getClass".equals(getterName)) {
                  continue;
              }
  
              // If the field is marked as JSONIgnore then ignore it
              if (entry.getValue().isAnnotationPresent(JSONIgnore.class)) {
                  continue;
              }
  
              String nameOfField = new StringBuilder().append(getterName.substring(3, 4).toLowerCase()).append(getterName.substring(4)).toString();
  
              if (haveIncompatibleFields && fieldsToPutInIncompatibleObject.contains(nameOfField)) {
                  addFieldToJsonObject(entry.getValue(), o, nameOfField, incompatibleFieldsObjectBuilder);
              } else {
                  addFieldToJsonObject(entry.getValue(), o, nameOfField, mainObjectBuilder);
              }
          }
          JsonObject mainObject = mainObjectBuilder.build();
          JsonObject incompatibleFieldsObject = null;
          if (incompatibleFieldsObjectBuilder != null) {
              incompatibleFieldsObject = incompatibleFieldsObjectBuilder.build();
          }
  
          return new JSONArtrifactPair(mainObject, incompatibleFieldsObject);
      }