I have a somewhat odd problem. I have a system of data objects fo significant size, with a wide variety of properties. They're being serialized and deserialized with JSON, and in many cases, the field names have been altered by annotation. I have users who interact with that JSON and could not care less what the underlying code does, as long as they know what to put int eh JSON to make it work right. I'd like to provide them with an endpoint they can go to, where they can identify a class, and have it spit back the field name (as it would appear in the serialized JSON). I have the class object and have some ability in working with reflection.

I have considered a few options. My initial plan was that I was just going to handle everything with reflection, but I realized that that would require me to chase around all of the Jackson-affecting annotations myself to try to get the logic right. That sounds like a huge amount of unnecessary effort that would almost certainly generate a few ugly and well-hidden bugs as I wound up getting the logic not-quite-right. Jackson already has this logic, after all. It seems like I should be able to harness it in some way.

I have considered making a dummy version of the class, serializing it, and reading the field names off of the JSON that results, but there are a large number of classes here, many of them are complicated, and many of them have properties that point at one another. Under those conditions, making the sort of field auto-populate that would make that work right... well, that also sounds like a great deal of hopefully-unnecessary, bug-generating work.

There is the logic in Jackson somewhere that knows how to identify these field names (specifically the serialized field names for the fields that actually are being serialized). It seems like it should be possible to determine just with the ObjectMapper and the class that I want the information on. Is it possible? How should I do it? I haven't been able to find instructions online (fuzzed-out by all the articles on how to change the name in the first place) and just reading the class files in Jackson isn't doing the trick either. (The comments are relatively terse, and what I'm looking for is very specific. Even if I did find it, I don't know how I would make sure that it was actually giving me the thing I need, rather than some other, very similar thing.)

As a bonus, if there were some way to know which java class the field had as its value, that would be even better, but I have at least a few workarounds for that that I think I might be able to make workable. Getting a precise field names is more important.

1

There are 1 best solutions below

0
On

Well, I managed to find my answer.

// We're using the jacksObjectMapper to grab the serializer, so that
// we can get the list of logical properties from said serializer.
// The point of this process is that we want to give the user the
// data that corresponds with what said user is looking at.  That
// means we specifically want the fields that jackson will serialize
// and deserialize, with the names that jackson will use.  This is
// the way to get that.  It was not as easy to find as you might think.

SerializerProvider serProv = jacksonObjectMapper.getSerializerProviderInstance();
JsonSerializer serializer = serProv.findValueSerializer(inputClass);

Iterator<PropertyWriter> logicalProperties = serializer.properties();

// Once we have the logical properties, we grab the field names and 
// value classes from that, and use that to populate everything else.
while (logicalProperties.hasNext()) {

    PropertyWriter propw = logicalProperties.next();
    String jsonFieldName = propw.getName();
    ...
}

Now past that point, it was still somewhat interesting to line it up with the java reflection fields that the properties were spawned from, so that I could actually get those value classes, but that was a different issue, and one with a solution far more dependent on the individual codebase.