Sorry, I think we're talking across each other slightly here. I'll try to explain again.

I think the most awkward thing about working with freeform data in a statically typed language is a timing issue. It's not that you don't need to do things like error handling in a dynamic language but you do in a static system; it's that in the dynamic language, you can typically choose when and where to do it, while static typing effectively forces you to do some of the heavy lifting up-front to convert the freeform data into types within your design in the first place.

You seem to be considering as your main example the serialisation of data between two sides of an app where you maintain both sides. Fair enough, that's one use case for something like JSON. But consider what happens if you want to use it as a simple interchange format so that your code on one side of an HTTP link can communicate with someone else's code on the other side using a well-specified protocol.

Maybe part of the incoming JSON says

{ "forename": "Chris", "surname": "Newton" }

but what you really want internally is to look up something from a database using those values as key.

In a dynamic language, you can typically just pull out the strings when you want them, plug them straight into your database API, and get the result you care about. If the values were missing or invalid, this is going to fail, but maybe it was going to fail anyway if the database didn't contain a matching record and so you've already got all the error recovery code you need in place.

With a static type system, in contrast, you probably need to parse the JSON into some type within your system as soon as it arrives. You can basically do that in one of two ways. One is to convert the JSON into some sort of general JSONObject/JSONArray/etc. classes, as for example the basic Java JSON library from json.org does. In that case, you retain the structural flexibility, but you also haven't really gained anything from using a static type system because you still have the hassle of manually navigating the resulting tree and doing all your type-checking later, which is a chore. The alternative is to parse the JSON into a more semantically meaningful type right from the start:

public class Person
{
String forename;
String surname;
}

That's nice, it gets the data into a format we understand, and if the parser can use reflection to figure out what kinds of fields to look for and what types they should be, so much the better. But now I'm stuck with this other class to maintain, tied to the external interface of my code rather than however I model things internally. If I want to handle errors gracefully, such as receiving text data where I expected an integer, I have to specify how to do it at that stage (which is where the metadata issue comes in if you're trying to use reflection to generate your parsers automatically). If I later change my external JSON protocol definition to add another field or (worse) change the structure a bit, I have to reconfigure my corresponding set of classes to match.

Now, I'm not saying this is necessarily a bad design. As I mentioned before, I think as a general principle it is usually best to validate and convert data as soon as it comes into a system anyway. However, for the kind of rapid prototyping development process that is widespread in web development, that kind of formality can get in the way in the early stages, and I think that is one reason that dynamic languages are popular for this type of work.