2017-02-16 2 views
3

Voici un simple code Java pour tester mon problème:problème de cartographie étrange JSON avec Set - manque un élément

ObjectMapper mapper = new ObjectMapper(); 
String s = "[\n" + 
      " {\n" + 
      "  \"id\": \"\",\n" + 
      "  \"name\": \"fsgh\",\n" + 
      "  \"email\": \"[email protected]\",\n" + 
      "  \"password\": \"fdg\"\n" + 
      " },\n" + 
      " {\n" + 
      "  \"id\": \"\",\n" + 
      "  \"name\": \"sdfg\",\n" + 
      "  \"email\": \"[email protected]\",\n" + 
      "  \"password\": \"dfghfgh\"\n" + 
      " }\n" + 
      " ]"; 
String jsonBody = "{\n" + 
      " \"id\": \"\",\n" + 
      " \"name\": \"<cxzzx\",\n" + 
      " \"email\": \"[email protected]\",\n" + 
      " \"address\": \"asd 72b\",\n" + 
      " \"zip\": \"1234\",\n" + 
      " \"city\": \"Asdf\",\n" + 
      " \"country\": \"Norway\",\n" + 
      " \"enabled\": \"true\",\n" + 
      " \"quota\": \"50\",\n" + 
      " \"expires\": \"2021-04-02\",\n" + 
      " \"adminAccounts\": " + 
      s + 
      "}"; 
Set<Account> accounts = mapper.readValue(s, Set.class); 
Organization organization = mapper.readValue(jsonBody, Organization.class); 

Maintenant vous pouvez voir du JSON que nous devrions avoir 2 comptes d'administration et les comptes objet est correct mais l'organisation n'a que le premier. Voici une capture d'écran des valeurs dans le débogueur: From debugger

Quelqu'un a des idées d'où cela vient-il?

+0

Comment sont AdminAccount (ou quelle que soit la classe est appelée) de 'égal à égal/hashCode mis en œuvre? J'ai remarqué que les deux comptes ont un identifiant vide. Si l'égalité d'un compte est basée sur id, alors le HashSet en omet (correctement) un en double. – yshavit

+0

@yshavit Il n'est pas implémenté dans la classe Account et je crois que cela serait également valable pour l'ensemble "accounts" qui a (correctement) les deux éléments – grekier

+0

Ah, bon point. À quoi ressemble un élément d'adminAccount? Cela donne-t-il une idée de ce qui se passe? – yshavit

Répondre

0

Je vous recommande vivement PAS pour utiliser la concaténation de chaînes, car jackson offre la possibilité d'y parvenir avec pojos. C'est propre et moins sujette aux erreurs.

d'abord déclarer un POJO pour le compte

public class Account { 

private String id; 

private String name; 

private String email; 

private String password; 


public Account(String id, String name, String email, String password) { 
    this.id = id; 
    this.name = name; 
    this.email = email; 
    this.password = password; 
} 

public String getId() { 
    return id; 
} 

public void setId(String id) { 
    this.id = id; 
} 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
} 

public String getEmail() { 
    return email; 
} 

public void setEmail(String email) { 
    this.email = email; 
} 

public String getPassword() { 
    return password; 
} 

public void setPassword(String password) { 
    this.password = password; 
} 
} 

Alors pour l'organisation. Notez que nous incluons la liste des comptes admin ici

public class Organization { 

private String id; 

private String email; 

private String name; 

private String address; 

private String zip; 

private String city; 

private String country; 

private boolean enabled; 

private int quota; 

private String expires; 

private List<Account> adminAccounts; 

public Organization(String id, String email, String name, String address, String zip, String city, String country, boolean enabled, int quota, String expires, List<Account> adminAccounts) { 
    this.id = id; 
    this.email = email; 
    this.name = name; 
    this.address = address; 
    this.zip = zip; 
    this.city = city; 
    this.country = country; 
    this.enabled = enabled; 
    this.quota = quota; 
    this.expires = expires; 
    this.adminAccounts = adminAccounts; 
} 

public String getId() { 
    return id; 
} 

public void setId(String id) { 
    this.id = id; 
} 

public String getEmail() { 
    return email; 
} 

public void setEmail(String email) { 
    this.email = email; 
} 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
} 

public String getAddress() { 
    return address; 
} 

public void setAddress(String address) { 
    this.address = address; 
} 

public String getZip() { 
    return zip; 
} 

public void setZip(String zip) { 
    this.zip = zip; 
} 

public String getCity() { 
    return city; 
} 

public void setCity(String city) { 
    this.city = city; 
} 

public String getCountry() { 
    return country; 
} 

public void setCountry(String country) { 
    this.country = country; 
} 

public boolean isEnabled() { 
    return enabled; 
} 

public void setEnabled(boolean enabled) { 
    this.enabled = enabled; 
} 

public int getQuota() { 
    return quota; 
} 

public void setQuota(int quota) { 
    this.quota = quota; 
} 

public String getExpires() { 
    return expires; 
} 

public void setExpires(String expires) { 
    this.expires = expires; 
} 

public List<Account> getAdminAccounts() { 
    return adminAccounts; 
} 

public void setAdminAccounts(List<Account> adminAccounts) { 
    this.adminAccounts = adminAccounts; 
} 
} 

Puis nous arrivons à la logique métier actuelle. Vous créez un certain nombre de comptes dont vous avez besoin

Account account1 = new Account("1", "name1", "email1", "pass1"); 
Account account2 = new Account("2", "name2", "email2", "pass2"); 

et les ajouter à une liste

List<Account> accounts = new ArrayList<Account>(); 
accounts.add(account1); 
accounts.add(account2); 

ensuite les ajouter à l'Organisation

Organization organization = new Organization("orgId", "orgEmail", "orgName", "orgAddress", "OrgZip", "orgCity", "orgCountry", true, 50, "2017-3-3", accounts); 

Fondamentalement, est représenté par les comptes de votre chaîne s et jsonBody représenté par l'organisation. Essayez de créer ces deux POJO compte d'abord et de l'organisation et de les manipuler comme des objets java

0

Voici le code je l'ai testé avec pour obtenir ce travail. J'utilise jackson-databind-2.8.6. Je soupçonne qu'il ya quelque chose d'étrange avec vos classes POJO ou il peut y avoir un bug dans la version de Jackson que vous utilisez:

public class JacksonTest { 

    public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException { 
     final ObjectMapper mapper = new ObjectMapper(); 
     final String s = "[\n" + 
     " {\n" + 
     "  \"id\": \"\",\n" + 
     "  \"name\": \"fsgh\",\n" + 
     "  \"email\": \"[email protected]\",\n" + 
     "  \"password\": \"fdg\"\n" + 
     " },\n" + 
     " {\n" + 
     "  \"id\": \"\",\n" + 
     "  \"name\": \"sdfg\",\n" + 
     "  \"email\": \"[email protected]\",\n" + 
     "  \"password\": \"dfghfgh\"\n" + 
     " }\n" + 
     " ]"; 
     final String jsonBody = "{\n" + 
     " \"id\": \"\",\n" + 
     " \"name\": \"<cxzzx\",\n" + 
     " \"email\": \"[email protected]\",\n" + 
     " \"address\": \"asd 72b\",\n" + 
     " \"zip\": \"1234\",\n" + 
     " \"city\": \"Asdf\",\n" + 
     " \"country\": \"Norway\",\n" + 
     " \"enabled\": \"true\",\n" + 
     " \"quota\": \"50\",\n" + 
     " \"expires\": \"2021-04-02\",\n" + 
     " \"adminAccounts\": " + s + 
     "}"; 

     final Set<Account> accounts = mapper.readValue(s, mapper.getTypeFactory().constructCollectionType(Set.class, Account.class)); 
     System.out.println("Accounts Size: " + accounts.size()); 
     System.out.println("Accounts: " + accounts); 

     System.out.println(); 

     final Organization organization = mapper.readValue(jsonBody, Organization.class); 
     System.out.println("Organization Admin Accounts Size: " + organization.adminAccounts.size()); 
     System.out.println("Organization Admin Accounts: " + organization.adminAccounts); 
    } 

    private static class Account { 
     @Override 
     public String toString() { 
     return "Account [id=" + this.id + ", name=" + this.name + ", email=" + this.email + ", password=" + this.password + "]"; 
     } 

     public String id, name, email, password; 
    } 

    private static class Organization { 
     @Override 
     public String toString() { 
     return "Organization [id=" + this.id + ", name=" + this.name + ", email=" + this.email + ", address=" + this.address + ", zip=" + 
      this.zip + ", city=" + 
      this.city + ", country=" + this.country + ", enabled=" + this.enabled + ", quota=" + this.quota + ", expires=" + this.expires + 
      ", adminAccounts=" + 
      this.adminAccounts + "]"; 
     } 

     public String id, name, email, address, zip, city, country, enabled, quota, expires; 
     public Set<Account> adminAccounts; 
    } 
} 
0

Je l'obtenir, pour s, Ce tableau ne comporte qu'un seul élément, s = « [ object1] "et object1 a deux éléments, donc accounts.size() = 2, organisation.adminAccounts = s =" [objet1] ", organization.adminAccounts.size() = 1, organization.adminAccounts est juste a object1. Vous voulez que organization.adminAccounts.size() = 2, organization.adminAccounts = "[[object2], [object3]]", donc s = "[[object2], [object3]]". Vous pouvez essayer ceci:

String s = "[\n" + 
     " [{\n" + 
     "  \"id\": \"\",\n" + 
     "  \"name\": \"fsgh\",\n" + 
     "  \"email\": \"[email protected]\",\n" + 
     "  \"password\": \"fdg\"\n" + 
     " }],\n" + 
     " [{\n" + 
     "  \"id\": \"\",\n" + 
     "  \"name\": \"sdfg\",\n" + 
     "  \"email\": \"[email protected]\",\n" + 
     "  \"password\": \"dfghfgh\"\n" + 
     " }]\n" + 
     " ]"; 

enter image description here