Jackson JSON处理器在反序列化期间覆盖对象的属性

时间:2011-10-25 08:08:33

标签: json properties deserialization jackson overwrite

我有一个有趣的问题。 Jackson使用具有相同名称的“child”对象的属性值覆盖“父”对象上的属性值。所以,更确切地说,这是我有的Java结构

public class Contact {
    ...
    String name;
    List<Email> emails;
    List<PhoneNumbers> phoneNumbers;
    Account account;
    ...
}

public class Account {
    ...
    String accountName;
    List<Email> emails;
    List<PhoneNumbers> phoneNumbers;
    Account account;
    ...
}

因此,当我形成Contact JSON对象并将其发送到服务器时,一切顺利,直到BeanDeserializer进入Contact类的帐户属性。然后,它开始阅读JSON的帐户部分的proeprties,这是好的,但是没有创建Account实例来设置联系 - 它将帐户属性的值写入具有相同名称的Contact实例的属性。

我很困惑,不知道从哪里开始寻找解决方法。

1 个答案:

答案 0 :(得分:1)

我无法重现任何类似于原始问题中描述的问题。

以下示例基于原始问题中的描述创建,按预期工作,没有错误或不正确的反序列化。

import java.util.LinkedList;
import java.util.List;

import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonCreator;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.ObjectMapper;

public class JacksonFoo
{
  public static void main(String[] args) throws Exception
  {
    Account account1 = new Account();
    account1.accountName = "account 1";
    account1.emails = new LinkedList<Email>();
    account1.emails.add(new Email("email_11@google.com"));
    account1.emails.add(new Email("email_12@google.com"));
    account1.phoneNumbers = new LinkedList<PhoneNumbers>();
    account1.phoneNumbers.add(new PhoneNumbers(1111, 1112));
    account1.phoneNumbers.add(new PhoneNumbers(1113, 1114));

    Account account2 = new Account();
    account2.accountName = "account 2";
    account2.emails = new LinkedList<Email>();
    account2.emails.add(new Email("email_21@google.com"));
    account2.emails.add(new Email("email_22@google.com"));
    account2.phoneNumbers = new LinkedList<PhoneNumbers>();
    account2.phoneNumbers.add(new PhoneNumbers(2221, 2222));
    account2.phoneNumbers.add(new PhoneNumbers(2223, 2224));
    account2.account = account1;

    Contact contact = new Contact();
    contact.name = "contact";
    contact.emails = new LinkedList<Email>();
    contact.emails.add(new Email("email_31@google.com"));
    contact.emails.add(new Email("email_32@google.com"));
    contact.phoneNumbers = new LinkedList<PhoneNumbers>();
    contact.phoneNumbers.add(new PhoneNumbers(3331, 3332));
    contact.phoneNumbers.add(new PhoneNumbers(3333, 3334));
    contact.account = account2;

    ObjectMapper mapper = new ObjectMapper();
    mapper.setVisibilityChecker(  
        mapper.getVisibilityChecker()  
          .withFieldVisibility(Visibility.ANY));

    String account1Json = mapper.writeValueAsString(account1);
    String account2Json = mapper.writeValueAsString(account2);
    String contactJson = mapper.writeValueAsString(contact);

    System.out.println(account1Json); // {"accountName":"account 1","emails":[{"email":"email_11@google.com"},{"email":"email_12@google.com"}],"phoneNumbers":[{"phone1":1111,"phone2":1112},{"phone1":1113,"phone2":1114}],"account":null}
    System.out.println(account2Json); // {"accountName":"account 2","emails":[{"email":"email_21@google.com"},{"email":"email_22@google.com"}],"phoneNumbers":[{"phone1":2221,"phone2":2222},{"phone1":2223,"phone2":2224}],"account":{"accountName":"account 1","emails":[{"email":"email_11@google.com"},{"email":"email_12@google.com"}],"phoneNumbers":[{"phone1":1111,"phone2":1112},{"phone1":1113,"phone2":1114}],"account":null}}
    System.out.println(contactJson); // {"name":"contact","emails":[{"email":"email_31@google.com"},{"email":"email_32@google.com"}],"phoneNumbers":[{"phone1":3331,"phone2":3332},{"phone1":3333,"phone2":3334}],"account":{"accountName":"account 2","emails":[{"email":"email_21@google.com"},{"email":"email_22@google.com"}],"phoneNumbers":[{"phone1":2221,"phone2":2222},{"phone1":2223,"phone2":2224}],"account":{"accountName":"account 1","emails":[{"email":"email_11@google.com"},{"email":"email_12@google.com"}],"phoneNumbers":[{"phone1":1111,"phone2":1112},{"phone1":1113,"phone2":1114}],"account":null}}}

    Account account1Copy = mapper.readValue(account1Json, Account.class);
    Account account2Copy = mapper.readValue(account2Json, Account.class);
    Contact contactCopy = mapper.readValue(contactJson, Contact.class);

    System.out.println(account1.equals(account1Copy)); // true
    System.out.println(account2.equals(account2Copy)); // true
    System.out.println(contact.equals(contactCopy)); // true
  }
}

class Contact
{
  String name;
  List<Email> emails;
  List<PhoneNumbers> phoneNumbers;
  Account account;

  @Override
  public boolean equals(Object o)
  {
    Contact c = (Contact) o;
    if (name.equals(c.name))
      if (emails.containsAll(c.emails))
        if (c.emails.containsAll(emails))
          if (phoneNumbers.containsAll(c.phoneNumbers))
            if (c.phoneNumbers.containsAll(phoneNumbers))
              return account.equals(c.account);
    return false;
  }
}

class Account
{
  String accountName;
  List<Email> emails;
  List<PhoneNumbers> phoneNumbers;
  Account account;

  @Override
  public boolean equals(Object o)
  {
    Account a = (Account) o;
    if (accountName.equals(a.accountName))
      if (emails.containsAll(a.emails))
        if (a.emails.containsAll(emails))
          if (phoneNumbers.containsAll(a.phoneNumbers))
            if (a.phoneNumbers.containsAll(phoneNumbers))
              if (account != null && a.account != null)
                return account.equals(a.account);
              else if (account == null && a.account == null)
                return true;
    return false;
  }
}

class Email
{
  String email;

  @JsonCreator
  Email(@JsonProperty("email") String e) {email = e;}

  @Override
  public boolean equals(Object o)
  {
    Email e = (Email) o;
    return email.equals(e.email);
  }
}

class PhoneNumbers
{
  long phone1;
  long phone2;

  @JsonCreator
  PhoneNumbers(@JsonProperty("phone1") long p1, @JsonProperty("phone2")long p2) {phone1 = p1; phone2 = p2;}

  @Override
  public boolean equals(Object o)
  {
    PhoneNumbers p = (PhoneNumbers) o;
    return phone1 == p.phone1 && phone2 == p.phone2;
  }
}